- JDK 动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
- JDK 和Cglib 都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类方式比 JDK效率低。
- JDK 调用代理方法,是通过反射机制调用,Cglib是通过 FastClass机制直接调用方法,Cglib执行效率更高。
- 同一个类中方法嵌套调用, 对内层方法增强 效果上区别
Cglib动态代理, proxy.invokeSuper(proxy, args) 使用方式, 对同一类中 test1()调用test2(), 俩者都被代理的情况下, 调用test1()方法时test1()、test2()都会被增强。 methodProxy.invoke(target, args), 只会对test1()方法增强。区别是传入的执行对象是代理对象 还是 被代理对象。
JDK动态代理, 对同一类中 test1()调用test2(), 俩者都被代理的情况下只会test1()方法增强, test2()方法不会被增强
解释:
- JDK 动态代理方式重写 java.lang.reflect.InvocationHandler#invoke 的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(">>>>>>>>>>>>>>>>>>>>>>");
Object result = method.invoke(target, args);
return result;
}
错误使用方式
- method.invoke(proxy, args), 会出现死循环
正确使用方式
- 传入目标类对象 target, 使用 method.invoke(target, args), 执行被代理类的目标方法
- Cglib动态代理方式重写 org.springframework.cglib.proxy.MethodInterceptor#intercept 的方法
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("这里是对目标类进行增强!!!" + method.getName());
//注意这里的方法调用,不是用反射哦!!!
Object object = proxy.invokeSuper(proxy, args);
return object;
}
错误使用方式
- proxy.invoke(proxy, args); 会出现死循环, 调用代理中的方法, 执行代理类中被增强的字方法 #test1()
正确使用方式
- 使用 proxy.invokeSuper(proxy, args); 调用代理中的方法, 通过执行代理类中被重写名字方法调用父类方法 #CGLIB$test1$2()
- 传入目标类对象 target, methodProxy.invoke(target, args); Spring CglibAopProxy 类使用的这种方式