Spring -- 06 -- JDK動態代理和CGLIB動態代理的區別
阿新 • • 發佈:2021-01-03
動態代理
反射的應用:動態代理
動態代理的好處:
我們只需要傳入需要代理的物件,即被代理物件,就會自動的建立相應的代理類物件,通過代理類物件操作被代理類物件
在動態代理之前,先來了解一下靜態代理模式
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("四川麻辣燙");
}
}
結果