標籤:
該文章轉自網路,原文不可考,給出轉載文章連結:http://blog.csdn.net/rokii/article/details/4046098
看項目代碼看到一段寫的很美的代理機制,整理一下:
動態代理其實就是java.lang.reflect.Proxy類動態根據您指定的所有介面產生一個class byte,該class會繼承Proxy類,並實現所有你指定的介面(您在參數中傳入的介面數組);然後再利用您指定的classloader將 class byte載入進系統,最後產生這樣一個類的對象,並初始化該對象的一些屬性,如invocationHandler,以及所有的介面對應的Method成員。 初始化之後將對象返回給調用的用戶端。這樣用戶端拿到的就是一個實現你所有的介面的Proxy對象。請看執行個體分析:
業務介面
public interface BusinessProcessor { public void processBusiness();}
業務介面實作類別
public class BusinessProcessorImpl implements BusinessProcessor { public void processBusiness() { System.out.println("processing business....."); }}
業務代理類
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class BusinessProcessorHandler implements InvocationHandler { private Object target = null; BusinessProcessorHandler(Object target){ this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("You can do something here before process your business"); Object result = method.invoke(target, args); System.out.println("You can do something here after process your business"); return result; }}
用戶端應用類
import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.lang.reflect.Proxy;public class Test { public static void main(String[] args) {
BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); bp.processBusiness(); }}
列印結果:
You can do something here before process your business
processing business.....
You can do something here after process your business
通過結果我們就能夠很簡單的看出Proxy的作用了,它能夠在你的核心業務方法前後做一些你所想做的輔助工作,如log日誌,安全機制等等。
現在我們來分析一下上面的類的工作原理。
類一二沒什麼好說的。
先看看類三吧:實現了InvocationHandler介面的invoke方法。其實這個類就是最終Proxy調用的固定介面方法。Proxy不管用戶端的業務方法是怎麼實現的。當用戶端調用Proxy時,它只
會調用InvocationHandler的invoke介面,所以我們的真正實現的方法就必須在invoke方法中去調用。關係如下:
BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);
bp.processBusiness()-->invocationHandler.invoke()-->bpimpl.processBusiness();
那麼bp到底是怎麼樣一個對象呢。我們改一下main方法看一下就知道了:
public static void main(String[] args) { BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); bp.processBusiness(); System.out.println(bp.getClass().getName()); }
輸出結果:
You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0
bp原來是個$Proxy0這個類的對象。那麼這個類到底是長什麼樣子呢?好的。我們再寫二個方法去把這個類列印出來看個究竟,是什麼三頭六臂呢?我們在main下面寫如下兩個靜態方法。
public static String getModifier(int modifier){ String result = ""; switch(modifier){ case Modifier.PRIVATE: result = "private"; case Modifier.PUBLIC: result = "public"; case Modifier.PROTECTED: result = "protected"; case Modifier.ABSTRACT : result = "abstract"; case Modifier.FINAL : result = "final"; case Modifier.NATIVE : result = "native"; case Modifier.STATIC : result = "static"; case Modifier.SYNCHRONIZED : result = "synchronized"; case Modifier.STRICT : result = "strict"; case Modifier.TRANSIENT : result = "transient"; case Modifier.VOLATILE : result = "volatile"; case Modifier.INTERFACE : result = "interface"; } return result; } public static void printClassDefinition(Class clz){ String clzModifier = getModifier(clz.getModifiers()); if(clzModifier!=null && !clzModifier.equals("")){ clzModifier = clzModifier + " "; } String superClz = clz.getSuperclass().getName(); if(superClz!=null && !superClz.equals("")){ superClz = "extends " + superClz; } Class[] interfaces = clz.getInterfaces(); String inters = ""; for(int i=0; i<interfaces.length; i++){ if(i==0){ inters += "implements "; } inters += interfaces[i].getName(); } System.out.println(clzModifier +clz.getName()+" " + superClz +" " + inters ); System.out.println("{"); Field[] fields = clz.getDeclaredFields(); for(int i=0; i<fields.length; i++){ String modifier = getModifier(fields[i].getModifiers()); if(modifier!=null && !modifier.equals("")){ modifier = modifier + " "; } String fieldName = fields[i].getName(); String fieldType = fields[i].getType().getName(); System.out.println(" "+modifier + fieldType + " "+ fieldName + ";"); } System.out.println(); Method[] methods = clz.getDeclaredMethods(); for(int i=0; i<methods.length; i++){ Method method = methods[i]; String modifier = getModifier(method.getModifiers()); if(modifier!=null && !modifier.equals("")){ modifier = modifier + " "; } String methodName = method.getName(); Class returnClz = method.getReturnType(); String retrunType = returnClz.getName(); Class[] clzs = method.getParameterTypes(); String paraList = "("; for(int j=0; j<clzs.length; j++){ paraList += clzs[j].getName(); if(j != clzs.length -1 ){ paraList += ", "; } } paraList += ")"; clzs = method.getExceptionTypes(); String exceptions = ""; for(int j=0; j<clzs.length; j++){ if(j==0){ exceptions += "throws "; } exceptions += clzs[j].getName(); if(j != clzs.length -1 ){ exceptions += ", "; } } exceptions += ";"; String methodPrototype = modifier +retrunType+" "+methodName+paraList+exceptions; System.out.println(" "+methodPrototype ); } System.out.println("}"); }View Code
再改寫main方法
public static void main(String[] args) { BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); bp.processBusiness(); System.out.println(bp.getClass().getName()); Class clz = bp.getClass(); printClassDefinition(clz); }
現在我們再看看輸出結果:
You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0
$Proxy0 extends java.lang.reflect.Proxy implements com.tom.proxy.dynamic.BusinessProcessor
{
java.lang.reflect.Method m4;
java.lang.reflect.Method m2;
java.lang.reflect.Method m0;
java.lang.reflect.Method m3;
java.lang.reflect.Method m1;
void processBusiness();
int hashCode();
boolean equals(java.lang.Object);
java.lang.String toString();
}
很明顯,Proxy.newProxyInstance方法會做如下幾件事:
1,根據傳入的第二個參數interfaces動態產生一個類,實現interfaces中的介面,該例中即BusinessProcessor介面的processBusiness方法。並且繼承了Proxy類,重寫了hashcode,toString,equals等三個方法。具體實現可參看 ProxyGenerator.generateProxyClass(...); 該例中產生了$Proxy0類
2,通過傳入的第一個參數classloder將剛產生的類載入到jvm中。即將$Proxy0類load
3,利用第三個參數,調用$Proxy0的$Proxy0(InvocationHandler)建構函式 建立$Proxy0的對象,並且用interfaces參數遍曆其所有介面的方法,並產生Method對象初始化對象的幾個Method成員變數
4,將$Proxy0的執行個體返回給用戶端。
現在好了。我們再看用戶端怎麼調就清楚了。
1,用戶端拿到的是$Proxy0的執行個體對象,由於$Proxy0繼承了BusinessProcessor,因此轉化為BusinessProcessor沒任何問題。
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);
2,bp.processBusiness();
實際上調用的是$Proxy0.processBusiness();那麼$Proxy0.processBusiness()的實現就是通過InvocationHandler去調用invoke方法啦!
[轉]深入理解Java Proxy機制