1. 程式人生 > 其它 >spring-動態代理模式

spring-動態代理模式

動態代理主要有兩種實現方式 :

  • 基於介面的動態代理 : JDK動態代理
  • 基於類的動態代理 : cglib

下面演示的是 JDK動態代理

1 JDK動態代理需要了解的一個介面和一個類

1.1 InvocationHandler (呼叫處理程式)

InvocationHandler 是生成代理例項的類需要實現的介面,然後需要實現介面中的 invoke() 方法,在這個方法中進行對代理例項的處理

1.2 Proxy (代理)

Proxy 是所有代理例項的父類,它提供了建立動態代理例項的靜態方法.

2 程式碼演示一

2.1 建立一個抽象物件

//租房
public interface Rend {
    public void rend();
}

2.2 建立一個 真實物件

public class Homeowner implements Rend {
    @Override
    public void rend(){
        System.out.println("房東出租了房子");
    }
}

3.3 建立一個生成代理例項的類(核心)

//這個類是用來生成代理例項的類
public class ProxyInvocationHandle implements InvocationHandler {

    //被代理的介面
    private Rend rend;

    public void setRend(Rend rend) {
        this.rend = rend;
    }

    //生成得到代理類
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rend.getClass().getInterfaces(),this);
    }

    //處理代理例項,並返回結果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //動態代理的本質,就是使用反射機制實現!
        seeHouse();
        Object result = method.invoke(rend, args);
        fare();
        return result;
    }

    public void seeHouse(){
        System.out.println("中介帶你看房子");
    }
    public void fare(){
        System.out.println("收中介費");
    }
}

3.4 建立客戶類

public class Client {
    public static void main(String[] args) {
        //真實角色
        Homeowner homeowner = new Homeowner();
        //代理角色:現在沒有
        ProxyInvocationHandle pih = new ProxyInvocationHandle();
        //通過呼叫程式處理角色來處理我們要呼叫的介面物件!
        pih.setRend(homeowner);
        Rend proxy = (Rend) pih.getProxy();//這裡的proxy就是動態生成的,我們並沒有寫
        proxy.rend();
    }
}

3.5 執行結果

3 程式碼演示二

3.1 建立一個抽象物件

public interface UserService {
    public void query();
    public void add();
    public void delete();
    public void update();
}

3.2 建立一個真實物件

public class UserServiceImpl implements UserService{
    @Override
    public void query() {
        System.out.println("查詢使用者");
    }
    @Override
    public void add() {
        System.out.println("增加使用者");
    }
    @Override
    public void delete() {
        System.out.println("刪除使用者");
    }
    @Override
    public void update() {
        System.out.println("修改使用者");
    }
}

3.3 建立一個生成代理例項的類(核心)

//用這個類,自動生成代理類
public class ProxyInvocationHandle implements InvocationHandler {

    //被代理的介面
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到代理類
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    //處理代理例項,並返回結果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //動態代理的本質,就是使用反射機制實現!
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }

    public void log(String msg){
        System.out.println("執行了"+msg+"方法");
    }
}

3.4 建立客戶類

public class Client {
    public static void main(String[] args) {
        //真實角色
        UserServiceImpl userService = new UserServiceImpl();
        //代理角色,不存在
        ProxyInvocationHandle pih = new ProxyInvocationHandle();
        pih.setTarget(userService);//設定要代理的物件
        //動態生成代理類
        UserService proxy = (UserService) pih.getProxy();
        proxy.add();
    }
}

3.5 執行結果

4 總結

  • 動態代理解決了靜態代理建立過多的代理類導致開發效率降低的問題
  • 動態代理的角色和靜態代理的是相同的
  • 動態代理的代理類是動態生成的 . 靜態代理的代理類是我們提前寫好的
  • 一個動態代理 , 一般代理某一類業務
  • 一個動態代理可以代理多個類,代理的是介面
  • 可以使得我們的真實角色更加純粹 . 不再去關注一些公共的事情
  • 公共的業務由代理來完成 . 實現了業務的分工
  • 公共業務發生擴充套件時變得更加集中和方便