Java動態代理

代理,就是需要代理類和被代理類有相同的對外接口或者說成服務,所以代理類一般都必須實現了所有被代理類已實現的接口,因爲接口就是制定了一系列對外服務的標準。

 

        正因爲動態代理有這樣靈活的特性,所以我們在設計動態代理類(DynamicProxy)時不用顯式地讓它實現與真實主題類(RealSubject)相同的接口(interface),而是把這種實現推遲到運行時。

        爲了能讓DynamicProxy類能夠在運行時纔去實現RealSubject類已實現的一系列接口並執行接口中相關的方法操作,需要讓DynamicProxy類實現JDK自帶的java.lang.reflect.InvocationHandler接口,該接口中的invoke()方法能夠讓DynamicProxy實例在運行時調用被代理類的“對外服務”,即調用被代理類需要對外實現的所有接口中的方法,也就是完成對真實方法的調用,Java幫助文檔中稱這些真實方法爲處理程序。

        我們肯定必須先把被代理類RealSubject已實現的所有interface都加載到JVM中,不然JVM怎麼能夠找到這些方法呢?明白了這個道理,那麼我們就可以創建一個被代理類的實例,獲得該實例的類加載器ClassLoader。

        所謂的類加載器ClassLoader,就是具有某個類的類定義,即類的內部相關結構(包括繼承樹、方法區等等)

        動態代理模式可以使得我們在不改變原來已有的代碼結構的情況下,對原來的“真實方法”進行擴展、增強其功能,並且可以達到控制被代理對象的行爲的目的。DynamicProxy類必須實現的invoke()方法在調用被代理類的真實方法的前後都可進行一定的特殊操作。這是動態代理最明顯的優點


爲了解決某些問題,比如,不允許直接訪問某些類;對訪問要做特殊處理等。或者,要對原方法進行統一的擴展,出現了動態代理需求

類圖


JDK動態代理中包含一個類和一個接口: 
InvocationHandler接口: 

public interface InvocationHandler { 
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 
} 


參數說明: 
Object proxy:指被代理的對象。 
Method method:要調用的方法 
Object[] args:方法調用時所需要的參數 

可以將InvocationHandler接口的子類想象成一個代理的最終操作類

接口中聲明的所有方法都被轉移到一個集中的方法中處理(invoke)

動態代理類只能代理接口,代理類都需要實現InvocationHandler類,實現invoke方法。該invoke方法就是調用被代理接口的所有方法時需要調用的,該invoke方法返回的值是被代理接口的一個實現類

主題接口

public interface ISubject {
	void doSomething();
}

真實對象

public class RealSubject implements ISubject {
	@Override
	public void doSomething() {
		System.out.println("+++RealSubject+++");
	}
}

handler

public class SubHandler implements InvocationHandler {
	private Object obj;// 持有真實對象
	public SubHandler(Object obj) {
		this.obj = obj;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = method.invoke(obj, args);// 真實對象來執行具體的方法
		System.out.println("dy proxy ");//加入自己操作
		return result;
	}
}

使用

public class Test {
	public static void main(String[] args) {
		RealSubject realSubject = new RealSubject();
		ISubject sub = (ISubject) Proxy.newProxyInstance(realSubject.getClass()
				.getClassLoader(), realSubject.getClass().getInterfaces(),
				new SubHandler(realSubject));
		sub.doSomething();
	}
}

//output

+++RealSubject+++

dy proxy






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