代理模式-靜態代理解讀

踏 浪發表於2020-11-04

1、介紹

定義:

代理模式:給某一個物件提供一個代理物件,並由代理物件控制對原物件的引用

拿買車做打比方。

沒有使用代理的情況,一個人去買二手車,他首先到店裡驗車,然後付款,最後自己再去車管所上牌。

使用代理的情況,他只需要找個中介,然後把款付給中介,讓中介幫我們去店裡驗車,付款,然後再幫我們去車管所上牌。

分類:

按照代理建立的時期來進行分類, 可以分成2類:

  • 靜態代理編譯期間 代理類的 .class 檔案已經被建立好了
  • 動代理態:執行期間 通過反射機制動態建立代理物件 動態代理有2種( JDK的動態代理 、cglib的動態代理

總結:

代理模式是:通過預編譯方式和執行期動態代理實現在不修改原始碼的情況下給程式動態統一新增功能的一種技術。

簡單的說,就是可以在業務方法執行之前,進行一些邏輯方法的處理,在業務方法執行之後,再進行另一些邏輯方法的處理。可以用代理模式來做 日誌記錄、許可權控制、事務處理、效能統計

 

 

 

2、靜態代理

案例:

有個 UserService 介面,在介面中定義了一個 save 方法。有個 UserServiceImpl 類實現了 UserService 介面,重寫了 save方法。此時我們需要在 不改變 UserServiceImpl 類的情況下,為 save 方法執行之前 新增開啟事務操作, 在執行 save 方法後 執行提交事務操作

例如:

原來的 save 方法:

    public void save(User user) {
        System.out.println("開始事務。。。。");
        System.out.println("正在儲存 ->" + user);
        System.out.println("提交事務。。。。");
    }

改造後的 save 方法:

    public void save(User user) {
        System.out.println("正在儲存 ->" + user);
    }

思考:為什麼要把事務處理的方法抽取處理?

試想下,我們很多方法都需要進行事務的處理,而事務處理方法的邏輯又是固定的,如果這些方法都自己進行事務處理,那麼在我們的業務方法中會冗餘很多這樣的程式碼,不便於後期的維護和升級

案例操作:

實體類:User 

package com.lcy.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Integer id;
    private String name;
}

業務層介面:UserService

package com.lcy.service;

import com.lcy.model.User;

public interface UserService {

    void save(User user);

}

介面的實現類:UserServiceImpl

package com.lcy.service.impl;

import com.lcy.model.User;
import com.lcy.service.UserService;

public class UserServiceImpl implements UserService {

    @Override
    public void save(User user) {
        System.out.println("正在儲存 ->" + user);
    }
}

代理類:UserServiceImplProxy

package com.lcy.proxy;

import com.lcy.model.User;
import com.lcy.service.UserService;

public class UserServiceImplProxy implements UserService {

    private UserService userService;

    public UserServiceImplProxy(UserService userService) {
        this.userService = userService;
    }


    @Override
    public void save(User user) {
        System.out.println("開始事務。。。。");

        userService.save(user);

        System.out.println("提交事務。。。。");
    }
}

測試類:UserServiceImplProxyTest

package com.lcy.test;

import com.lcy.model.User;
import com.lcy.proxy.UserServiceImplProxy;
import com.lcy.service.UserService;
import com.lcy.service.impl.UserServiceImpl;

public class UserServiceImplProxyTest {

    public static void main(String[] args) {
        
        UserService userService = new UserServiceImpl();
        UserService userServiceProxy = new UserServiceImplProxy(userService);
        userServiceProxy.save(new User(2, "張三"));
    }

}

 

執行結果:

設計分析圖:

3、靜態代理的優缺點

優點:在不改動原有的類的情況下,對其功能進行擴充套件

缺點:由於代理類也要實現介面,一旦介面發生變化(新增或刪除方法),代理類也要進行相應的修改。

相關文章