动态代理

来源:互联网 发布:如何选择网络机顶盒 编辑:程序博客网 时间:2024/06/05 10:19

参考文献:

http://www.jianshu.com/p/6f6bb2f0ece9

http://wiki.jikexueyuan.com/project/java-reflection/java-dynamic.html


动态代理的好处

  • 动态代理中接口中的所有方法都能转移到handler的一个invoke方法中处理;静态代理中每个方法都要有一个对应的代理增强方法;
  • 静态代理中修改接口时,所有的代理类都要修改;而动态代理不用修改;

JDK动态代理的原理

  • 通过Proxy.newInstace()方法动态生成代理类,然后返回代理类的对象,并在代理对象中注入handler作为属性;
  • 代理类的对象调用方法时,都被转到handler的invoke()方法来执行;

动态代理的底层实现

  • 生成代理的过程

static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler){    //1. 根据类加载器和接口动态创建代理类    Class clazz = Proxy.getProxyClass(loader, interfaces);     //2. 获得代理类的带参数的构造函数    Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });    //3. 创建代理对象,并制定调用处理器实例为参数传入    Interface Proxy = (Interface)constructor.newInstance(new Object[] {handler});}

  • 生成的代理类,以及方法怎么转到handler上的
public final class $Proxy1 extends Proxy implements Subject{    private InvocationHandler h;    private $Proxy1(){}    //把handler注入到代理对象中    public $Proxy1(InvocationHandler h){        this.h = h;    }    //代理类实现的接口方法    public int request(int i){    //获取委托类的Method对象;然后调用handler的invoke()方法,并传入proxy,method对象和参数;    Method method = Subject.class.getMethod("request", new Class[]{int.class});    return (Integer)h.invoke(this, method, new Object[]{new Integer(i)});     }}
  • 自定义的Handler类,以及如何增强方法
public class MyInvocationHandler implements InvocationHandler{    //    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    //在method执行前do something    //根据args参数,执行method对应的方法    //在method执行后do something  }}

CGLIB动态代理

  • CGLIB通过修改字节码来实现代理;JDK动态代理在运行时通过反射和动态编译来生成类的字节码,然后加载到JVM中;
  • spring中如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP;
  • spring中如果目标对象实现了接口,可以强制使用CGLIB实现AOP;
  • spring中如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换;


0 0
原创粉丝点击