java动态代理和cglib动态代理

来源:互联网 发布:淘宝质量问题怎么赔偿 编辑:程序博客网 时间:2024/05/18 15:06

本文转自: 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 plain copy
  1. package leon.aj.dynproxy.target;  
  2.   
  3. public interface Hello {  
  4.     public String sayHello(String name);  
  5. }  
实现类:

[java] view plain copy
  1. package leon.aj.dynproxy.target;  
  2.   
  3. public class HelloImpl implements Hello {  
  4.     @Override  
  5.     public String sayHello(String name) {  
  6.         String s = "Hello, "+name;  
  7.         System.out.println(this.getClass().getName()+"->"+s);  
  8.         return s;  
  9.     }  
  10. }  
另一接口和实现类:

[java] view plain copy
  1. package leon.aj.dynproxy.target;  
  2.   
  3. public interface UserDao {  
  4.     public boolean login(String username,String password);  
  5. }  

[java] view plain copy
  1. package leon.aj.dynproxy.target;  
  2.   
  3. public class UserDaoImpl implements UserDao {  
  4.     @Override  
  5.     public boolean login(String username, String password) {  
  6.         String user = "("+username+","+password+")";  
  7.         System.out.println(this.getClass().getName()+"-> processing login:"+user);  
  8.         return true;  
  9.     }  
  10. }  

应用Java API实现的动态代理类:

[java] view plain copy
  1. package leon.aj.dynproxy.java;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5. import java.lang.reflect.Proxy;  
  6.   
  7. public class JavaDynProxy implements InvocationHandler{  
  8.     private Object target;  
  9.     public Object getProxyInstance(Object target){  
  10.         this.target = target;  
  11.         return Proxy.newProxyInstance(target.getClass().getClassLoader(),   
  12.                 target.getClass().getInterfaces(), this);  
  13.     }  
  14.       
  15.     @Override  
  16.     public Object invoke(Object proxy, Method method, Object[] args)  
  17.             throws Throwable {  
  18.         Object result = null;  
  19.         System.out.println("before target method...");  
  20.         result = method.invoke(target, args);  
  21.         System.out.println("after target method...");  
  22.         return result;  
  23.     }  
  24. }  

测试:

[java] view plain copy
  1. package leon.aj.dynproxy.java;  
  2.   
  3. import leon.aj.dynproxy.target.Hello;  
  4. import leon.aj.dynproxy.target.HelloImpl;  
  5. import leon.aj.dynproxy.target.UserDao;  
  6. import leon.aj.dynproxy.target.UserDaoImpl;  
  7.   
  8. public class TestJavaProxy {  
  9.     public static void main(String[] args) {  
  10.         JavaDynProxy proxy = new JavaDynProxy();  
  11.         Hello hello = (Hello)proxy.getProxyInstance(new HelloImpl());  
  12.         String s = hello.sayHello("Leon");  
  13.         System.out.println(s);  
  14.           
  15.         UserDao userDao = (UserDao) proxy.getProxyInstance(new UserDaoImpl());  
  16.         userDao.login("Leon""1234");  
  17.         System.out.println(userDao.getClass().getName());  
  18.     }  
  19. }  

下面是采用cglib实现的例子(推荐):

性能方面看其他文章写的是cglib要略高一筹, 因为jdk代理大量使用反射的方式。而反射比较耗费性能,cglib就没有这一个顾虑,他直接就是调用生成的子类的方法。

[java] view plain copy
  1. package leon.aj.dynproxy.cglib;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import net.sf.cglib.proxy.Enhancer;  
  6. import net.sf.cglib.proxy.MethodInterceptor;  
  7. import net.sf.cglib.proxy.MethodProxy;  
  8.   
  9. public class CglibProxy implements MethodInterceptor {  
  10.     private Object target;    
  11.       
  12.     public Object getProxyInstance(Object target) {    
  13.         this.target = target;  
  14.         Enhancer enhancer = new Enhancer();    
  15.         enhancer.setSuperclass(this.target.getClass());    
  16.         enhancer.setCallback(this);  // call back method  
  17.         return enhancer.create();  // create proxy instance  
  18.     }    
  19.       
  20.     @Override  
  21.     public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
  22.         System.out.println("before target method...");  
  23.         Object result = proxy.invokeSuper(target, args);  
  24.         System.out.println("after target method...");  
  25.         return result;  
  26.     }  
  27. }  

测试类:

[java] view plain copy
  1. package leon.aj.dynproxy.cglib;  
  2.   
  3. import leon.aj.dynproxy.target.Hello;  
  4. import leon.aj.dynproxy.target.HelloImpl;  
  5. import leon.aj.dynproxy.target.UserDaoImpl;  
  6.   
  7. public class TestCiglib {  
  8.     public static void main(String[] args) {  
  9.         CglibProxy proxy = new CglibProxy();  
  10.         Hello hello = (Hello) proxy.getProxyInstance(new HelloImpl());  
  11.         System.out.println(hello.sayHello("Leon"));  
  12.         UserDaoImpl userDao = (UserDaoImpl) proxy.getProxyInstance(new UserDaoImpl());  
  13.         userDao.login("Leon""1234");  
  14.         System.out.println(userDao.getClass().getSuperclass());//看动态代理实例的父类  
  15.     }  
  16. }  


0 0