JDK動態代理和CGLiB動態代理

  1. JDK動態代理java

    JDK動態代理要求類必須實現某一接口,代理類是同一接口的實現類。性能

    JDK動態代理主要涉及兩個類:Proxy和InvocationHandler。InvocationHandler是一個接口,能夠經過實現該接口定義橫切邏輯,並經過反射機制調用目標類的代碼,動態的將橫切邏輯與業務邏輯交織在一塊兒。Proxy利用InvocationHandler動態建立一個符合某一接口的實例,生成目標類的代理對象。this

    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來實現代理。code

    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倍。get

    對於singleton的代理對象或具備實例池的代理,由於無需頻繁的建立代理對象,因此適合使用CGLiB代理,繁殖則使用JDK動態代理。io

    因爲CGLIB動態代理採用動態建立子類的方式生成代理對象,因此不能對目標類中 的final方法進行代理class

相關文章
相關標籤/搜索