JDK动态代理和CGLiB动态代理

  1. JDK动态代理

    JDK动态代理要求类必须实现某一接口,代理类是同一接口的实现类。

    JDK动态代理主要涉及两个类:Proxy和InvocationHandler。InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑与业务逻辑交织在一起。Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。

    public class MyInvocationHandler implements InvocationHandler {
         private Object target;
        public MyInvocationHandler(Object target){
              this.target = target;
        }
        public Object invoke(Object proxy, Method method, Object[] args) {
              begin();
              Object obj = method.invoke(target, args);
              end();
              return obj;
         }
    }
         
    创建代理实例
    public class Test {
         public static void main(String [] args){
              Target target = new TargetImpl();
               MyInvocationHandler handler = new MyInvocationHandler(target);
               Target proxy = (Target) Proxy.newProxyInstance(
                       target.getClass().getClassLoader(),
                       target.getInterfaces(),
                       handler);
                proxy.test();
         }
    }
  2. CGLiB动态代理

    JDK动态代理有一个缺点,就是它只能为接口创建代理实例。对于没有通过接口实现业务逻辑的类,通过CGLiB来实现代理。

    CGLiB采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势织入横切逻辑。

    public class CglibProxy implements MethodInterceptor {
         private Enhancer enhancer = new Enhancer();
         public Object getProxy(Class clazz) {
              enhancer.setSuperclass(clazz);
              enhancer.setCallback(this);
              return enhancer.create();
         }
         public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
              begin();
              Object result = proxy.invokeSuper(obj, args);
             end();
             return result;
         }
    }
    
    创建动态代理
    public class Test {
         public static void main(String [] args) {
              CglibProxy proxy = new CglibProxy();
             TargetImpl target = (TargetImpl) proxy.getProxy(TargetImpl.class);
             target.test();
             
         }
    }

  3. 对比

    CGLiB所创建的动态代理对象要比JDK所创建的动态代理对象的性能要高出10倍,但CGLiB创建动态代理所花费的时间却比JDK动态代理多8倍。

    对于singleton的代理对象或具有实例池的代理,因为无需频繁的创建代理对象,所以适合使用CGLiB代理,繁殖则使用JDK动态代理。

    由于CGLIB动态代理采用动态创建子类的方式生成代理对象,所以不能对目标类中 的final方法进行代理

你可能感兴趣的:(JDK动态代理和CGLiB动态代理)