該文章轉自網絡,原文不可考,給出轉載文章連接:http://blog.csdn.net/rokii/article/details/4046098java
看項目代碼看到一段寫的很美的代理機制,整理一下:數組
動態代理其實就是java.lang.reflect.Proxy類動態的根據您指定的全部接口生成一個class byte,該class會繼承Proxy類,並實現全部你指定的接口(您在參數中傳入的接口數組);而後再利用您指定的classloader將 class byte加載進系統,最後生成這樣一個類的對象,並初始化該對象的一些屬性,如invocationHandler,以及全部的接口對應的Method成員。 初始化以後將對象返回給調用的客戶端。這樣客戶端拿到的就是一個實現你全部的接口的Proxy對象。請看實例分析:安全
業務接口網絡
public interface BusinessProcessor { public void processBusiness(); }
業務接口實現類jvm
public class BusinessProcessorImpl implements BusinessProcessor { public void processBusiness() { System.out.println("processing business....."); } }
業務代理類ide
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(); } }
打印結果:this
You can do something here before process your business
processing business.....
You can do something here after process your businessspa
經過結果咱們就可以很簡單的看出Proxy的做用了,它可以在你的核心業務方法先後作一些你所想作的輔助工做,如log日誌,安全機制等等。.net
如今咱們來分析一下上面的類的工做原理。
類一二沒什麼好說的。
先看看類三吧:實現了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("}"); }
再改寫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類load3,利用第三個參數,調用$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方法啦!