上一篇: 對靜態(tài)代理的理解
接上一篇贴唇,學(xué)習(xí)了靜態(tài)代理后再來看看動態(tài)代理的機制秦陋。
在上一篇博客中灾梦,我們使用靜態(tài)代理實現(xiàn)了在修改登錄模塊代碼的情況下增加上報需求野舶,但是有個缺點:新增登錄方式必須新建代理類,例如要實現(xiàn)QQ登錄巾遭,必須新建QQLogin肉康、QQLoginProxy......,如果這種需求多來一點那代理類會爆炸灼舍,動態(tài)代理可以解決這個問題吼和。
實現(xiàn)
新建動態(tài)代理類:
import org.springframework.cglib.proxy.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxyHandler implements InvocationHandler {
private Object realObject;
public DynamicProxyHandler(Object realObject) {
this.realObject = realObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理擴展邏輯
System.out.println("動態(tài)代理類 開始執(zhí)行操作...");
System.out.println( "打印動態(tài)代理方法Method:" + method);
return method.invoke(realObject, args);
}
}
是用方法:
import org.springframework.cglib.proxy.Proxy;
public class Test {
public static void main(String[] args) {
//使用賬號密碼登錄
Login realObject = new Login();
LoginInterface loginInterface = (LoginInterface) Proxy.newProxyInstance(LoginInterface.class.getClassLoader(), new Class[]{LoginInterface.class}, new DynamicProxyHandler(realObject));
loginInterface.print();
loginInterface.test();
//使用微信登錄
WechatLogin wechatLogin = new WechatLogin();
LoginInterface loginInterface1 = (LoginInterface) Proxy.newProxyInstance(LoginInterface.class.getClassLoader(), new Class[]{LoginInterface.class}, new DynamicProxyHandler(wechatLogin));
loginInterface1.print();
}
}
打印結(jié)果:
動態(tài)代理類 開始執(zhí)行操作...
打印動態(tài)代理方法Method:public abstract void com.demo.springcloud.client1.client1.LoginInterface.print()
專注于賬號密碼登錄中...
動態(tài)代理類 開始執(zhí)行操作...
打印動態(tài)代理方法Method:public abstract void com.demo.springcloud.client1.client1.LoginInterface.test()
測試打印方法...
動態(tài)代理類 開始執(zhí)行操作...
打印動態(tài)代理方法Method:public abstract void com.demo.springcloud.client1.client1.LoginInterface.print()
專注于微信登錄中...
一個動態(tài)代理實現(xiàn)就完成了,不需要再寫什么LoginProxy和wechatLoginProxy這樣的代理類骑素,一個DynamicProxyHandler 就行了炫乓。
原理
代理類實現(xiàn)了InvocationHandler 類,重寫方法
public Object invoke(Object proxy, Method method, Object[] args)
proxy: 我們所代理的那個真實對象
method: 我們所要調(diào)用真實對象的某個方法的Method對象
args: 調(diào)用真實對象某個方法時接受的參數(shù)
所以打印結(jié)果里,method打印為
Method:public abstract void com.demo.springcloud.client1.client1.LoginInterface.print()
Method:public abstract void com.demo.springcloud.client1.client1.LoginInterface.test()
調(diào)用哪個方法末捣,就會動態(tài)傳入哪個方法為參數(shù)并執(zhí)行侠姑。
動態(tài)代理相對于靜態(tài)代理優(yōu)勢有以下幾點:
1.不再需要手動創(chuàng)建對應(yīng)代理類,例如:LoginProxy箩做、WechatLoginProxy
2.可以代理任意實現(xiàn)了LoginInterface接口的類對象莽红,并執(zhí)行接口的任意方法