博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java动态代理和cglib动态代理
阅读量:5870 次
发布时间:2019-06-19

本文共 4669 字,大约阅读时间需要 15 分钟。

hot3.png

动态代理应用广泛,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的。

下面是实现的例子。

首先,为了看到动态代理可以根据不同类动态产生不同代理的效果,我们新建两个接口,及其实现类。

package leon.aj.dynproxy.target;    public interface Hello {      public String sayHello(String name);  }

实现类:

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;      }  }

另一接口和实现类:

package leon.aj.dynproxy.target;    public interface UserDao {      public boolean login(String username,String password);  }
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实现的动态代理类:

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;      }  }

测试:

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实现的例子:

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);  // call back method          return enhancer.create();  // create proxy instance      }              @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;      }  }

测试类:

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());//看动态代理实例的父类      }  }

转载于:https://my.oschina.net/u/1866821/blog/362493

你可能感兴趣的文章