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