生活随笔
收集整理的這篇文章主要介紹了
jdk动态代理实现原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
寫在前面:
大神和diao炸天的親請繞道..
關于代理模式的概念這里省去,大家可以放鳥盡情搜..
關于為什么叫動態代理,個人理解是代理的類是在運行時動態生成的,大家也可以參考網上的理解..
文筆很差,所以文字較少,都在代碼和注釋中..
=======一點不華麗的分割線-------------------------
開門見山,lets?Go..
Java中可以通過jdk提供的 Proxy.newProxyInstance靜態方法來創建動態代理對象,下面先來看看這個方法的實現
[java]?view plaincopy
public?static?Object?newProxyInstance(ClassLoader?loader,?Class<?>[]?interfaces,?InvocationHandler?h)?? ???????????throws?IllegalArgumentException?{?? ????????? ????????? ???????if?(h?==?null)?{?? ???????????throw?new?NullPointerException();?? ???????}?? ?? ????????? ????????? ????????? ???????Class?cl?=?getProxyClass(loader,?interfaces);?? ?? ????????? ????????? ???????try?{?? ???????????Constructor?cons?=?cl.getConstructor(constructorParams);?? ???????????return?(Object)?cons.newInstance(new?Object[]?{?h?});?? ???????}?catch?(NoSuchMethodException?e)?{?? ???????????throw?new?InternalError(e.toString());?? ???????}?catch?(IllegalAccessException?e)?{?? ???????????throw?new?InternalError(e.toString());?? ???????}?catch?(InstantiationException?e)?{?? ???????????throw?new?InternalError(e.toString());?? ???????}?catch?(InvocationTargetException?e)?{?? ???????????throw?new?InternalError(e.toString());?? ???????}?? ???}??
下面通過個例子來說明下:
先來定義一個接口,jdk的動態代理基于接口來創建代理類,不能基于類的原因是java不支持多重繼承,而代理類都會繼承Proxy類(個人理解).
[java]?view plaincopy
? ? ? ? ? ?? public?interface?Subject?{?? ????void?pub(String?key,?String?content);?? ?? ????String?sub(String?key);?? }??
再來一個具體的實現,在代理模式中可以叫它的實例可以叫target,這個是真正執行操作的對象
[java]?view plaincopy
? ? ? ? ? ?? public?class?SimpleSubject?implements?Subject?{?? ????private?Map<String,?String>?msg?=?new?ConcurrentHashMap<String,?String>();?? ?? ????public?void?pub(String?key,?String?content)?{?? ????????System.out.println("pub?msg:?key?is?"?+?key?+?",?content?is?"?+?content);?? ????????msg.put(key,?content);?? ????}?? ?? ????public?String?sub(String?key)?{?? ????????if?(msg.containsKey(key))?{?? ????????????String?ret?=?msg.get(key);?? ????????????System.out.println("sub?msg:?key?is?"?+?key?+?",?result?is?"?+?ret);?? ????????????return?ret;?? ????????}?? ?? ????????return?null;?? ????}?? ?? }??
好,接下來我們來寫個動態代理工廠,根據 不同的target來創建動態代理對象
[java]?view plaincopy
? ? ? ? ? ?? public?class?SubjectProxyFactory?{?? ?????? ????public?static?Subject?getSubject(final?Subject?realSubject)?{?? ????????return?(Subject)?Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),?new?Class[]?{?Subject.class?},?? ????????????????new?InvocationHandler()?{?? ?? ????????????????????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{?? ????????????????????????System.out.println("\naction?before?method?invocation....");?? ????????????????????????Object?retVal?=?method.invoke(realSubject,?args);?? ????????????????????????System.out.println("action?after?method?invocation....\n");?? ????????????????????????return?retVal;?? ????????????????????}?? ????????????????});?? ????}?? }??
可以看到這是一個簡單的實現,只是在真實對象執行前后各打一句信息..
接下來用一個 main函數來把這些結合起來?
[java]?view plaincopy
? ? ? ? ? ?? public?class?Demo?{?? ????public?static?void?main(String[]?args)?{?? ?????????? ????????System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles",?"true");?? ?????????? ?????????? ????????Subject?subj?=?new?SimpleSubject();?? ????????subj.pub("name",?"kevin.fan");?? ????????subj.sub("name");?? ?????????? ?????????? ????????Subject?proxy?=?SubjectProxyFactory.getSubject(subj);?? ????????proxy.pub("hobby",?"r&b?music");?? ????????proxy.sub("name");?? ????}?? }??
ok,小手抖一下,走你,看下執行結果
[html]?view plaincopy
pub?msg:?key?is?name,?content?is?kevin.fan?? sub?msg:?key?is?name,?result?is?kevin.fan?? ?? ?? action?before?method?invocation....?? pub?msg:?key?is?hobby,?content?is?r&b?music?? action?after?method?invocation....?? ?? ?? ?? ?? action?before?method?invocation....?? sub?msg:?key?is?name,?result?is?kevin.fan?? action?after?method?invocation....??
可以看到在調用代理對象的方法時,添加的額外動作已經生效,接下來我們看下生成的代理類的代碼..
[java]?view plaincopy
import?com.aliyun.demo.kevin.coder.lang.proxy.Subject;?? import?java.lang.reflect.InvocationHandler;?? import?java.lang.reflect.Method;?? import?java.lang.reflect.Proxy;?? import?java.lang.reflect.UndeclaredThrowableException;?? ?? ?? public?final?class?$Proxy0?extends?Proxy?? ??implements?Subject?? {?? ???? ???? ??private?static?Method?m4;?? ??private?static?Method?m1;?? ??private?static?Method?m3;?? ??private?static?Method?m0;?? ??private?static?Method?m2;?? ???? ??static?? ??{?? ????try?? ????{?? ??????m4?=?Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("sub",?new?Class[]?{?Class.forName("java.lang.String")?});?? ??????m1?=?Class.forName("java.lang.Object").getMethod("equals",?new?Class[]?{?Class.forName("java.lang.Object")?});?? ??????m3?=?Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("pub",?new?Class[]?{?Class.forName("java.lang.String"),?Class.forName("java.lang.String")?});?? ??????m0?=?Class.forName("java.lang.Object").getMethod("hashCode",?new?Class[0]);?? ??????m2?=?Class.forName("java.lang.Object").getMethod("toString",?new?Class[0]);?? ??????return;?? ????}?? ????catch?(NoSuchMethodException?localNoSuchMethodException)?? ????{?? ??????throw?new?NoSuchMethodError(localNoSuchMethodException.getMessage());?? ????}?? ????catch?(ClassNotFoundException?localClassNotFoundException)?? ????{?? ??????throw?new?NoClassDefFoundError(localClassNotFoundException.getMessage());?? ????}?? ??}?? ?? ???? ???? ??public?$Proxy0?paramInvocationHandler)?? ????throws??? ??{?? ????super(paramInvocationHandler);?? ??}?? ?? ???? ??public?final?String?sub(String?paramString)?? ????throws??? ??{?? ????try?? ????{?? ????????? ??????return?(String)this.h.invoke(this,?m4,?new?Object[]?{?paramString?});?? ????}?? ????catch?(Error|RuntimeException?localError)?? ????{?? ??????throw?localError;?? ????}?? ????catch?(Throwable?localThrowable)?? ????{?? ??????throw?new?UndeclaredThrowableException(localThrowable);?? ????}?? ??}?? ?? ??public?final?boolean?equals(Object?paramObject)?? ????throws??? ??{?? ????try?? ????{?? ??????return?((Boolean)this.h.invoke(this,?m1,?new?Object[]?{?paramObject?})).booleanValue();?? ????}?? ????catch?(Error|RuntimeException?localError)?? ????{?? ??????throw?localError;?? ????}?? ????catch?(Throwable?localThrowable)?? ????{?? ??????throw?new?UndeclaredThrowableException(localThrowable);?? ????}?? ??}?? ?? ??public?final?void?pub(String?paramString1,?String?paramString2)?? ????throws??? ??{?? ????try?? ????{?? ??????this.h.invoke(this,?m3,?new?Object[]?{?paramString1,?paramString2?});?? ??????return;?? ????}?? ????catch?(Error|RuntimeException?localError)?? ????{?? ??????throw?localError;?? ????}?? ????catch?(Throwable?localThrowable)?? ????{?? ??????throw?new?UndeclaredThrowableException(localThrowable);?? ????}?? ??}?? ?? ??public?final?int?hashCode()?? ????throws??? ??{?? ????try?? ????{?? ??????return?((Integer)this.h.invoke(this,?m0,?null)).intValue();?? ????}?? ????catch?(Error|RuntimeException?localError)?? ????{?? ??????throw?localError;?? ????}?? ????catch?(Throwable?localThrowable)?? ????{?? ??????throw?new?UndeclaredThrowableException(localThrowable);?? ????}?? ??}?? ?? ??public?final?String?toString()?? ????throws??? ??{?? ????try?? ????{?? ??????return?(String)this.h.invoke(this,?m2,?null);?? ????}?? ????catch?(Error|RuntimeException?localError)?? ????{?? ??????throw?localError;?? ????}?? ????catch?(Throwable?localThrowable)?? ????{?? ??????throw?new?UndeclaredThrowableException(localThrowable);?? ????}?? ??}?? ?? }??
-------------END
by Kevin Fan
from:?http://blog.csdn.net/moreevan/article/details/11642445
總結
以上是生活随笔為你收集整理的jdk动态代理实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。