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(); } }
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(); } }
對比接口
CGLiB所建立的動態代理對象要比JDK所建立的動態代理對象的性能要高出10倍,但CGLiB建立動態代理所花費的時間卻比JDK動態代理多8倍。get
對於singleton的代理對象或具備實例池的代理,由於無需頻繁的建立代理對象,因此適合使用CGLiB代理,繁殖則使用JDK動態代理。io
因爲CGLIB動態代理採用動態建立子類的方式生成代理對象,因此不能對目標類中 的final方法進行代理class