一:在看此篇代碼示例前,先看靜態代理, java
連接地址:http://my.oschina.net/dyyweb/blog/656760 (代碼示例) 程序員
二:JDK動態代理 web
動態代理與靜態代理類對照的是動態代理類,動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。動態代理類不只簡化了編程工做,並且提升了軟件系統的可擴展性,由於Java 反射機制能夠生成任意類型的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力
編程
/** *定義一種類型的女人,王婆和潘金蓮都屬於這個類型的女人 */ public interface KindWoman { //這種女人能作什麼事情呢? public void makeEyesWithMan();//拋媚眼 public void happyWithMan();//和男人那個.... }
/** * 潘金蓮 */ public class PanJinLian implements KindWoman{ @Override public void happyWithMan() { System.out.println("潘金蓮和男人在作那個..."); } @Override public void makeEyesWithMan() { System.out.println("潘金蓮拋媚眼..."); } }
/** * 那咱們再考慮一下,水滸裏面還有沒有這類型的女人? * 有,盧俊義的老婆賈氏(就是和那個管家苟合的那個),這個名字起的:「賈氏」,那咱們也讓王婆作她的代理: */ public class JiaShi implements KindWoman{ @Override public void happyWithMan() { System.out.println("賈氏和男人在作那個..."); } @Override public 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); } @Override public 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:方法調用時所須要的參數 app
能夠將InvocationHandler接口的子類想象成一個代理的最終操做類,替換掉ProxySubject。 ide
Proxy類:
Proxy類是專門完成代理的操做類,能夠經過此類爲一個或多個接口動態地生成實現類,此類提供了以下的操做方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
參數說明:
ClassLoader loader:類加載器
Class<?>[] interfaces:獲得所有的接口
InvocationHandler h:獲得InvocationHandler接口的子類實例 this
Ps:類加載器
在Proxy類中的newProxyInstance()方法中須要一個ClassLoader類的實例,ClassLoader實際上對應的是類加載器,在Java中主要有一下三種類加載器;
Booststrap ClassLoader:此加載器採用C++編寫,通常開發中是看不到的;
Extendsion ClassLoader:用來進行擴展類的加載,通常對應的是jre\lib\ext目錄中的類;
AppClassLoader:(默認)加載classpath指定的類,是最常使用的是一種加載器。 spa
可是,JDK的動態代理依靠接口實現,若是有些類並無實現接口,則不能使用JDK代理,這就要使用cglib動態代理了。 .net
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(); } @Override public 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();