Java動態代理及原理

代理模式應該都不陌生。

Java通過反射機制,提供了代理模式的實現。其使用到的核心類如下:InvocationHandler接口  Proxy類

先看示例:

接口:

public interface MyInterface {
	void method();
}

接口實現類:

public class MyInterfaceImpl implements MyInterface {

	public void method() {
		System.out.println("method");
	}

}
代理類:
public class MyProxy implements InvocationHandler {

	Object obj;

	public ProxyClass(Object o) {
		obj = o;
	}

	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = null;
		try {
			System.out.println("before the method is called ");
			result = method.invoke(obj, args);
		} catch (Exception e) {
		} finally {
			System.out.println("after the method is called");
		}
		return result;
	}
}

調用類:

public class Main {
	public static void main(String[] argv) throws Exception {
		MyInterface myintf = (MyInterface) Proxy.newProxyInstance(                                                1
				MyInterface.class.getClassLoader(),
				new Class[] { MyInterface.class }, new MyProxy(                                           2
						new MyInterfaceImpl()));
		System.out.println(myintf instanceof Proxy);

		myintf.method();                                               
	}
}

需要關注的是代理類的實現。自JDK1.3之後,每一個代理的實例會有一個InvocationHandler對應。當代理實例的方法被調用的時候,改方法將會被編譯並且發送到對應的InvocationHandler的invoke方法上。

這裏需要注意兩處代碼:

1. new ProxyClass(new MyInterfaceImpl()) 對應MyProxy中的 result = method.invoke(obj, args); 該處很簡單,就是對實際方法的調用執行。

2.Proxy.newProxyInstance


先看參數:1.ClassLoader loader 代理類的加載體 2. Class<?>[] interfaces 代理類的繼承接口。3 InvocationHandler h 上面的MyProxy

代理類的集成接口,這裏有多個的原因,是因爲一個類可能會實現多個接口。


接下來:

Class cl = getProxyClass(loader, interfaces);

通過loader和interfaces創建代理類。具體方法如下:

 try {
		interfaceClass = Class.forName(interfaceName, false, loader);
	    } catch (ClassNotFoundException e) {
	    }

Proxy.class

接下來進行緩存處理:

synchronized (loaderToCache) {
	    cache = (Map) loaderToCache.get(loader);
	    if (cache == null) {
		cache = new HashMap();
		loaderToCache.put(loader, cache);
	    }
最後,返回已經創建的接口。


當創建好這個接口之後,JDK所作的是   Constructor cons = cl.getConstructor(constructorParams);  而這個constructorParams是什麼,這個constructorParams就是InvocationHandler.class 就是說所有Proxy的實現方法的接口。

在這裏,便得到了Constructor 然後再通過newInstance去得到這個代理的實類。


在這裏應該比較明白了,所謂的代理,在1處創建的是Proxy的對象,而這個Object繼承的接口則是MyInterface,當然了,運行方法還是爲定義的method,只不過是,創建代理的時候,就已經將method包裝,實際上執行的只不過爲invoke中的方法罷了。


至於Proxy使用場景:無非就是對前置有驗證或者類似的一半情況了。Spring的interceptor就是用的這種模式,但是javaee的filter用的不是這種模式,是回調模式。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章