jdk動態代理基本實現
動態代理的實現主要包括三部分:
介面:宣告業務方法
代理物件:真正物件的代理物件,通過真正物件的業務方法實現抽象類或介面的方法,並可附加自己的業務邏輯
真是物件:實現介面的方法,供代理物件呼叫
jdk中建立動態代理主要通過java.lang.reflect.Proxy類的
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException)方法。它的第一個引數是真實物件的類載入器,可以通過物件的.getClass().getClassLoader()獲取
第二個引數是真實物件實現的介面,可以通過物件的.getClass().getInterfaces()獲取
第三個引數是實現InvocationHandler介面的物件,通過api可知InvocationHandler是代理例項的呼叫處理程式 實現的介面,主要用於監聽代理物件呼叫方法來呼叫真實物件的方法,它底層採用的是觀察者模式。
InvocationHandler介面是一個函式式介面,它只有一個invoke(Object proxy, Method method, Object[] args)
方法,當代理物件呼叫方法時,會執行此方法。它的
第一個引數是代理物件
第二個引數是真實物件要呼叫方法,即呼叫的方法物件
第三個物件是呼叫方法的引數
如下:
首先建立一個介面:
public interface ITarget {
public void show();
}
真實物件實現介面:
public class Target implements ITarget {
@Override
public void show() {
System.out.println("-----------------show");
}
}
建立代理物件呼叫真實物件介面:
@Test public void test1() { //System.out.println("------------"); ITarget target = new Target(); //建立代理物件 ITarget targetProxy = (ITarget) Proxy.newProxyInstance( target.getClass().getClassLoader(), //真實物件的類載入器 target.getClass().getInterfaces(), //真實物件實現的介面 (Object proxy, Method method, Object[] args) -> { System.out.println("附加的功能...日誌、開啟事務等等"); Object object = method.invoke(target, args);//呼叫真實目標方法,引數1為真實物件 System.out.println("附加的功能...結束時間、提交事務等等"); return object; } ); targetProxy.show();//代理物件呼叫方法。 }
當代理物件呼叫show()方法時,會執行InvocationHandler實現類中的invoke方法,並將代理物件傳入invoke方法proxy引數,將要執行的方法傳入method,並將方法引數傳入args。而此時invoke方法真正呼叫真實物件方法的是method.invoke方法(第一個引數為真實物件,第二個引數為真實物件方法的引數,即InvocationHandler實現類中的invoke方法中的args),而在執行此方法是可以在此方法前後新增附加功能。當然在執行method.invoke一般會用Object來接收返回值,這樣當真實物件執行後有返回值時這樣代理物件也會接收到返回值。