生活随笔
收集整理的這篇文章主要介紹了
java动态代理和cglib动态代理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文轉自: http://blog.csdn.net/leon709/article/details/9529307
動態代理應用廣泛,spring,Struts等框架很多功能是通過動態代理,或者進一步封裝來實現的。
常見的動態代理模式實現有Java?API提供的動態代理和第三方開源類庫CGLIB動態代理。
Java?API提供的動態代理是基于類反射實現的,用到的類有:
java.lang.reflect.InvocationHandler;
java.lang.reflect.Method;
java.lang.reflect.Proxy;
其實現是通過Proxy類的newProxyInstance()方法產生代理對象。自定義動態代理類需要實現InvocationHandler接口,該接口只有一個invoke()方法。
CGLIB是通過生成java 字節碼從而動態的產生代理對象,因此需要字節碼解析處理的依賴asm類庫,字節碼動態生成的代理對象實際上是繼承了真實主題類的。這種實現方式需要導入cglib和asm的類庫。下面用到的例子是cglib-2.2.2.jar,?asm-3.3.1.jar。cglib使用了MethodInterceptor,其中的方法是intercept(),這是攔截的概念,很容易就想到了Struts2的攔截器。
比較之下,Java API提供的動態代理需要面向接口,產生代理對象,因此真實主題實現類必須實現了接口才可以。而CGLIB不需要面向接口,可以代理簡單類,但由于動態代理對象是繼承真實主題實現類的,因此要求真實主題實現類不能是final的。
下面是實現的例子。
首先,為了看到動態代理可以根據不同類動態產生不同代理的效果,我們新建兩個接口,及其實現類。
[java]?view plaincopy
package?leon.aj.dynproxy.target;?? ?? public?interface?Hello?{?? ????public?String?sayHello(String?name);?? }??
實現類:
[java]?view plaincopy
package?leon.aj.dynproxy.target;?? ?? public?class?HelloImpl?implements?Hello?{?? ????@Override?? ????public?String?sayHello(String?name)?{?? ????????String?s?=?"Hello,?"+name;?? ????????System.out.println(this.getClass().getName()+"->"+s);?? ????????return?s;?? ????}?? }??
另一接口和實現類:
[java]?view plaincopy
package?leon.aj.dynproxy.target;?? ?? public?interface?UserDao?{?? ????public?boolean?login(String?username,String?password);?? }??
[java]?view plaincopy
package?leon.aj.dynproxy.target;?? ?? public?class?UserDaoImpl?implements?UserDao?{?? ????@Override?? ????public?boolean?login(String?username,?String?password)?{?? ????????String?user?=?"("+username+","+password+")";?? ????????System.out.println(this.getClass().getName()+"->?processing?login:"+user);?? ????????return?true;?? ????}?? }??
應用Java API實現的動態代理類:
[java]?view plaincopy
package?leon.aj.dynproxy.java;?? ?? import?java.lang.reflect.InvocationHandler;?? import?java.lang.reflect.Method;?? import?java.lang.reflect.Proxy;?? ?? public?class?JavaDynProxy?implements?InvocationHandler{?? ????private?Object?target;?? ????public?Object?getProxyInstance(Object?target){?? ????????this.target?=?target;?? ????????return?Proxy.newProxyInstance(target.getClass().getClassLoader(),??? ????????????????target.getClass().getInterfaces(),?this);?? ????}?? ?????? ????@Override?? ????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?? ????????????throws?Throwable?{?? ????????Object?result?=?null;?? ????????System.out.println("before?target?method...");?? ????????result?=?method.invoke(target,?args);?? ????????System.out.println("after?target?method...");?? ????????return?result;?? ????}?? }??
測試:
[java]?view plaincopy
package?leon.aj.dynproxy.java;?? ?? import?leon.aj.dynproxy.target.Hello;?? import?leon.aj.dynproxy.target.HelloImpl;?? import?leon.aj.dynproxy.target.UserDao;?? import?leon.aj.dynproxy.target.UserDaoImpl;?? ?? public?class?TestJavaProxy?{?? ????public?static?void?main(String[]?args)?{?? ????????JavaDynProxy?proxy?=?new?JavaDynProxy();?? ????????Hello?hello?=?(Hello)proxy.getProxyInstance(new?HelloImpl());?? ????????String?s?=?hello.sayHello("Leon");?? ????????System.out.println(s);?? ?????????? ????????UserDao?userDao?=?(UserDao)?proxy.getProxyInstance(new?UserDaoImpl());?? ????????userDao.login("Leon",?"1234");?? ????????System.out.println(userDao.getClass().getName());?? ????}?? }??
下面是采用cglib實現的例子(推薦):
性能方面看其他文章寫的是cglib要略高一籌,?因為jdk代理大量使用反射的方式。而反射比較耗費性能,cglib就沒有這一個顧慮,他直接就是調用生成的子類的方法。
[java]?view plaincopy
package?leon.aj.dynproxy.cglib;?? ?? import?java.lang.reflect.Method;?? ?? import?net.sf.cglib.proxy.Enhancer;?? import?net.sf.cglib.proxy.MethodInterceptor;?? import?net.sf.cglib.proxy.MethodProxy;?? ?? public?class?CglibProxy?implements?MethodInterceptor?{?? ????private?Object?target;???? ?????? ????public?Object?getProxyInstance(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?target,?Method?method,?Object[]?args,?MethodProxy?proxy)?throws?Throwable?{?? ????????System.out.println("before?target?method...");?? ????????Object?result?=?proxy.invokeSuper(target,?args);?? ????????System.out.println("after?target?method...");?? ????????return?result;?? ????}?? }??
測試類:
[java]?view plaincopy
package?leon.aj.dynproxy.cglib;?? ?? import?leon.aj.dynproxy.target.Hello;?? import?leon.aj.dynproxy.target.HelloImpl;?? import?leon.aj.dynproxy.target.UserDaoImpl;?? ?? public?class?TestCiglib?{?? ????public?static?void?main(String[]?args)?{?? ????????CglibProxy?proxy?=?new?CglibProxy();?? ????????Hello?hello?=?(Hello)?proxy.getProxyInstance(new?HelloImpl());?? ????????System.out.println(hello.sayHello("Leon"));?? ????????UserDaoImpl?userDao?=?(UserDaoImpl)?proxy.getProxyInstance(new?UserDaoImpl());?? ????????userDao.login("Leon",?"1234");?? ????????System.out.println(userDao.getClass().getSuperclass());?? ????}?? }??
總結
以上是生活随笔為你收集整理的java动态代理和cglib动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。