1. 程式人生 > >jdk動態代理基本實現

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來接收返回值,這樣當真實物件執行後有返回值時這樣代理物件也會接收到返回值