Python基礎 2.5 包,程式碼規範,案例
阿新 • • 發佈:2021-01-18
技術標籤:java
什麼是動態代理?
1、在程式執行時,運用反射機制動態建立而成,無需手動編寫程式碼。
2、JDK動態代理和靜態代理一樣,目標類需要實現一個代理介面,在通過代理物件呼叫目標方法。
好處:
動態代理與靜態代理相比較,最大的好處是介面中宣告的所有的方法都被轉移到呼叫處理器一個集中的方法中處理,解耦和易維護。
實操:
定義一個java.lang.reflect.InvocationHandler介面的實現類,重寫invoke方法
//Object proxy:被代理的物件
//Method method:要呼叫的方法
//Object[] args:方法呼叫時所需要引數
public class JdkProxy implements InvocationHandler {
//目標類
private Object targetObject;
//獲取代理物件
public Object newProxyInstance(Object targetObject){
this. targetObject = targetObject;
//繫結關係,也就是和具體的哪個實現類關聯
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader (),
targetObject.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) {
Object result = null;
try{
System.out.println("通過JDK動態代理呼叫 "+method.getName() +", 列印日誌 begin");
result = method.invoke(targetObject,args);
System.out.println("通過JDK動態代理呼叫 "+method.getName() +", 列印日誌 end");
}catch (Exception e){
e.printStackTrace();
}
return result;
}
}
目標介面:
public interface PayService {
/**
* 支付回撥
* @param outTradeNo
* @return
*/
String callback(String outTradeNo);
/**
* 下單
* @param userId
* @param productId
* @return
*/
int save(int userId,int productId);
}
目標實現類:
public class PayServiceImpl implements PayService {
public String callback(String outTradeNo) {
System.out.println("目標類 PayServiceImpl 回撥 方法 callback");
return outTradeNo;
}
public int save(int userId, int productId) {
System.out.println("目標類 PayServiceImpl 回撥 方法 save");
return productId;
}
}
實現方法:
public static void main(String [] args){
//JDK動態代理
JdkProxy jdkProxy = new JdkProxy();
//獲取代理類物件
PayService payServiceProxy = (PayService)jdkProxy.newProxyInstance(new PayServiceImpl());
//呼叫目標方法
payServiceProxy.callback("dsfsdfdsfew");
payServiceProxy.save(23,42423);
}
執行結果:
兩種動態代理的區別:
1、 JDK動態代理:要求目標物件實現一個介面,但是有時候目標物件只是一個單獨的物件,並沒有實現任何的介面,這個時候就可以用CGLib動態代理
2、CGLib動態代理,它是在記憶體中構建一個子類物件從而實現對目標物件功能的擴充套件 JDK動態代理是自帶的,CGlib需要引入第三方包
3、CGLib動態代理基於繼承來實現代理,所以無法對final類、private方法和static方法實現代理
Spring AOP中的代理使用的預設策略:
1、如果目標物件實現了介面,則預設採用JDK動態代理
2、如果目標物件沒有實現介面,則採用CgLib進行動態代理
3、如果目標物件實現了介面,程式裡面依舊可以指定使用CGlib動態代理