為什么80%的碼農都做不了架構師?>>> ??
一:在看此篇代碼示例前,先看靜態代理,
鏈接地址: http://my.oschina.net/dyyweb/blog/656760 ? ?(代碼示例)
二:JDK動態代理
動態代理 與靜態代理類對照的是動態代理類,動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。動態代理類不僅簡化了編程工作,而且提高了軟件系統的可擴展性,因為Java 反射機制可以生成任意類型的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力
/***定義一種類型的女人,王婆和潘金蓮都屬于這個類型的女人*/
public interface KindWoman {//這種女人能做什么事情呢?public void makeEyesWithMan();//拋媚眼public void happyWithMan();//和男人那個....
}
/*** 潘金蓮*/
public class PanJinLian implements KindWoman{@Overridepublic void happyWithMan() {System.out.println("潘金蓮和男人在做那個...");}@Overridepublic void makeEyesWithMan() {System.out.println("潘金蓮拋媚眼...");}
}
/*** 那我們再考慮一下,水滸里面還有沒有這類型的女人?* 有,盧俊義的老婆賈氏(就是和那個管家茍合的那個),這個名字起的:“賈氏”,那我們也讓王婆做她的代理:*/
public class JiaShi implements KindWoman{@Overridepublic void happyWithMan() {System.out.println("賈氏和男人在做那個...");}@Overridepublic void makeEyesWithMan() {System.out.println("賈氏拋媚眼...");}
}
/*** jdk動態代理** 王婆變身動態代理*/
public class WangPoProxy implements InvocationHandler{private Object target;//綁定委托對象并返回一個代理類public Object createProxyTarget(Object target){this.target = target;//取得代理對象,要綁定接口(這是一個缺陷,cglib彌補了這一缺陷)return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.err.println("+++++++++開始切入++++++++++++");Object result=method.invoke(target, args); //執行方法System.err.println("+++++++++++結束切入++++++++++");return result;}
}
public class XiMenQiang {public static void main(String[] args) {//王婆出廠WangPoProxy wangPo = new WangPoProxy();//潘金蓮出場PanJinLian panJinLian = new PanJinLian();//告王婆代理潘金蓮茍且之事KindWoman woman = (KindWoman) wangPo.createProxyTarget(panJinLian);//然后西門慶說,我要和潘金蓮Happy,然后王婆就安排了西門慶丟筷子哪出戲:woman.makeEyesWithMan();//看到沒有表面是王婆在做,其實爽的是潘金蓮woman.happyWithMan();//西門慶勾引賈氏JiaShi jiaShi = new JiaShi();woman = (KindWoman) wangPo.createProxyTarget(jiaShi);woman.makeEyesWithMan();woman.happyWithMan();}
}
JDK動態代理中包含一個類和一個接口:? InvocationHandler接口:? public interface InvocationHandler {? public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;? }? 參數說明:? Object proxy:指被代理的對象。? Method method:要調用的方法? Object[] args:方法調用時所需要的參數?
可以將InvocationHandler接口的子類想象成一個代理的最終操作類,替換掉ProxySubject。?
Proxy類:? Proxy類是專門完成代理的操作類,可以通過此類為一個或多個接口動態地生成實現類,此類提供了如下的操作方法:? public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,? InvocationHandler h)? ?????????????????????????????? throws IllegalArgumentException? 參數說明:? ClassLoader loader:類加載器? Class<?>[] interfaces:得到全部的接口? InvocationHandler h:得到InvocationHandler接口的子類實例?
Ps:類加載器? 在Proxy類中的newProxyInstance()方法中需要一個ClassLoader類的實例,ClassLoader實際上對應的是類加載器,在Java中主要有一下三種類加載器;? Booststrap ClassLoader:此加載器采用C++編寫,一般開發中是看不到的;? Extendsion ClassLoader:用來進行擴展類的加載,一般對應的是jre\lib\ext目錄中的類;? AppClassLoader:(默認)加載classpath指定的類,是最常使用的是一種加載器。?
三:
但是,JDK的動態代理依靠接口實現,如果有些類并沒有實現接口,則不能使用JDK代理,這就要使用cglib動態代理了。?
Cglib動態代理? JDK的動態代理機制只能代理實現了接口的類,而不能實現接口的類就不能實現JDK的動態代理,cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。?
這里用了兩個jar,asm-3.3.1.jar 和cglib-2.2.2.jar 注意版本號哦,不然坑
/**** 相信你一定也知道水滸傳的拼命三郎石秀吧,他的結拜兄弟楊雄的老婆,潘云巧也是個水性楊花的女人* 他和師兄(一個和尚偷情)*/
public class PanYunQiao {public void betrayal(){System.out.println("正在和和尚偷情...");}
}
*** cglib動態代理** 王婆變身動態代理** cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。*/
public class WangPoCglibProxy implements MethodInterceptor {private Object target;/*** 創建代理對象** @param target* @return*/public Object getInstance(Object target) {this.target = target;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(this.target.getClass());// 回調方法enhancer.setCallback(this);// 創建代理對象return enhancer.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.err.println("+++++++++cglib開始切入++++++++++++");methodProxy.invokeSuper(obj, args);System.err.println("+++++++++++cglib結束切入++++++++++");return null;}
}
/*** cglib動態代理*/WangPoCglibProxy wangPoCglibProxy = new WangPoCglibProxy();PanYunQiao panYunQiao = new PanYunQiao();PanYunQiao pan = (PanYunQiao) wangPoCglibProxy.getInstance(panYunQiao);pan.betrayal();
轉載于:https://my.oschina.net/dyyweb/blog/659462
總結
以上是生活随笔 為你收集整理的动态代理,动态代理设计模式 ,JDK动态代理,cglib动态代理 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。