1. 程式人生 > 其它 >Spring -- 06 -- JDK動態代理和CGLIB動態代理的區別

Spring -- 06 -- JDK動態代理和CGLIB動態代理的區別

技術標籤:設計模式反射java

動態代理

反射的應用:動態代理

動態代理的好處:

我們只需要傳入需要代理的物件,即被代理物件,就會自動的建立相應的代理類物件,通過代理類物件操作被代理類物件

在動態代理之前,先來了解一下靜態代理模式

public interface ClothFactory {
    void produceCloth();
}

代理類

public class ProxyClothFactory implements ClothFactory {
    //代理模式的關鍵程式碼
    private ClothFactory factory;//用被代理類物件進行例項化
public ProxyClothFactory(ClothFactory factory) { this.factory = factory; } //--------------------------------- @Override public void produceCloth() { System.out.println("代理工廠做一些準備工作"); factory.produceCloth(); System.out.println("代理工廠做一些收尾工作"
); } }

被代理類

public class NikeClothFatory implements ClothFactory {
    @Override
    public void produceCloth() {
        System.out.println("Nike工廠生產一批運動服");
    }
}

測試類

public class Test01 {
    public static void main(String[] args) {
        //建立被代理類物件
        ClothFactory nike = new
NikeClothFatory(); //建立代理類的物件 ClothFactory proxyClothFatory = new ProxyClothFactory(nike); proxyClothFatory.produceCloth(); } }

結果

在這裡插入圖片描述

動態代理問題:

問題一:如何根據載入到記憶體中的被代理類,動態的建立一個代理類以及物件。

問題二:當通過代理類的物件呼叫物件時,如何動態的去呼叫被代理類中的同名方法。

動態代理例項

介面

public interface Human {
    String getBelief();
    void eat(String food);
}

被代理類

public class SuperMan implements Human{
    @Override
    public String getBelief() {
        return "I believe I can fly";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜歡吃"+food);
    }
}

解決問題一

public class ProxyFactory  {
    //呼叫此方法,返回一個代理類的物件。
    public static Object getProxyInstance(Object obj){//obj:被代理類物件
        MyInvocationHandler handler = new MyInvocationHandler(obj);

        /*
        newProxyInstance():第一個引數被代理類的類載入器,
        第二個引數被代理類的實現的介面
        第三個引數InvocationHandler介面實現類
         */
        //關鍵程式碼
        Object instance = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
        return instance;

    }
}

解決問題二

public class MyInvocationHandler implements InvocationHandler {

    private Object obj;//需要使用被代理類的物件進行賦值
    
    public MyInvocationHandler(Object obj) {
        this.obj = obj;
    }

    //當我們通過代理類的物件,呼叫a時,就會自動呼叫如下的方法:invoke()
    //將被代理類要執行的方法a的功能就宣告在invoke()中
    //關鍵程式碼
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //method:即為代理類物件呼叫的方法,此方法作為代理類物件要呼叫的方法
        //obj:被代理類的物件
        Object invoke = method.invoke(obj, args);
        return invoke;
    }
}

測試類

public class Test01 {
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        //proxyInstance:代理類的物件
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        String belief = proxyInstance.getBelief();
        System.out.println(belief);
        proxyInstance.eat("四川麻辣燙");
    }
}

結果

在這裡插入圖片描述