一、原理区别
Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理
JDK动态代理和CGLIB字节码生成的区别?
(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
二,代理实现
JDK动态代理
1.实现InvocationHandler
2.提供接口public class MyInvocationHandler implements InvocationHandler{ /** * 要代理的目标对象 */ private Object target; public MyInvocationHandler(Object target) { this.target = target; } /** * 执行方法 * @param proxy * @param method * @param args * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("方法执行之前..."); Object result = method.invoke(this.target,args); System.out.println("方法执行之后..."); return result; } /** * 生成代理对象 * @return */ public Object getProxy(){ return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), this.target.getClass().getInterfaces(),this); } }
3.子类实现接口public interface Person{ void makeFriend(String name); }
4.测试类public class ZhangSan implements Person { @Override public void makeFriend(String name) { System.out.println("和"+name+"交了个朋友"); } }
5.打印结果public class ProxyTest { public static void main(String[] args) { MyInvocationHandler myInvocationHandler = new MyInvocationHandler(new ZhangSan()); Person person = (Person) myInvocationHandler.getProxy(); //System.out.println(person); person.makeFriend("林志玲"); } }
方法执行之前...
和林志玲交了个朋友
方法执行之后...
CGLIB动态代理1.提供目标类
2.生成代理类public class XiaoMing { void sayHello(){ System.out.println("hello everyone"); } }
3.测试public class CglibProxy implements MethodInterceptor { public Object getProxy(Class clazz){ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz);//设置代理类的父类为目标类 enhancer.setCallback(this);//回调 return enhancer.create();//生成代理类 } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable { //生成代理类是子类,因此调用父类的方法 Object obj = proxy.invokeSuper(o, args); return obj; } }
4.打印结果public class CglibTest { public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); XiaoMing xiaoMing = (XiaoMing) cglibProxy.getProxy(XiaoMing.class); xiaoMing.sayHello(); } }
hello everyone
三,总结
jdk代理
代理对象和目标对象实现了相同了接口,目标对象作为代理对象的一个属性在维护,此代理模式在使用时需要制定具体目标对象,并且只针对实现了接口的类生成代理
cglib代理
cglib代理是针对类实现代理,生成的是目标类的子类代理对象,覆盖其所有方法,所以目标类或方法不能声明成final的。如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)
cglib动态创建代理对象性能比jdk创建效率要高,对于单例对象,cglib更适合,不用频繁创建对象;反之jdk代理更适合