1.JDK 动态代理(实现InvocationHandler),只能实现对接口的动态代理
public class JDKProxyTest { public static void main(String[] args) { TargetI ti = new Target(); JDKProxyTarget handler = new JDKProxyTarget(ti); TargetI pti = (TargetI) Proxy.newProxyInstance(ti.getClass().getClassLoader(), ti.getClass().getInterfaces(), handler); pti.say(); } } interface TargetI { public void say(); } class Target implements TargetI { @Override public void say() { System.out.println("Target say()"); } } class JDKProxyTarget implements InvocationHandler { private Object target; public JDKProxyTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("jdkproxy before"); Object obj = method.invoke(target, args); System.out.println("jdkproxy after"); return obj; } }
2.cglib动态代理,采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类的调用,并顺势织入横切逻辑。
public class CglibProxyTest { public static void main(String[] args) { CglibProxy cp = new CglibProxy(); Target2 t2 = (Target2) cp.getProxy(Target2.class); t2.say(); } } class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz) { enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("before"); Object result = proxy.invokeSuper(obj, args); System.out.println("after"); return result; } } class Target2 { public void say() { System.out.println("target2 say()"); } }
JDK动态代理所创建的代理对象,在JDK1.3下,性能差强人意。虽然在高版本的JDK中,动态代理对象的性能得到了很大的提高,但是有研究表明,CGLib所创建的动态代理对象的性能依旧比JDK的所创建的代理对象的性能高不少(大概10倍)。但CGLib在创建代理对象时所花费的时间却比JDK动态代理多(大概8倍),所以对于singleton的代理对象或者具有实例池的代理,因为无需频繁创建代理对象,所以比较适合用CGLib动态代理技术,反之适合JDK动态代理技术。值得一提的是,由于CGLib采用动态 创建子类的方式生成代理对象,所以不能对目标类中的final,private等方法进行代理。