JDK动态代理
JDK的动态代理只允许代理接口
重要的类和接口Proxy和InvocationHandler
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)方法创建目标对象的代理对象
获取到目标对象的代理对象之后,执行目标对象的方法实际上是通过调用代理对象的invoke方法实现的
我们可以在invoke方法中增加额外的通用的逻辑来对目标对象进行增强
1 | typescript复制代码/** |
获取到代理对象之后,像调用目标对象一样调用代理对象的方法,直观上和普通的调用没有任何区别,但是实际上调用的是代理对象的invoke方法,在invoke方法里面可以做的事情有很多,可以增强甚至重写某些方法,通过method.getName()来对指定方法进行处理
1 | scala复制代码public class ProxyHandlerTest extends TestInit { |
使用Cglib实现动态代理
Cglib不是jdk自带的jar包,需要下载并加入到项目中
CGLIB代理相关的类:
- net.sf.cglib.proxy.Enhancer 主要的增强类。
- net.sf.cglib.proxy.MethodInterceptor 主要的方法拦截类,它是Callback接口的子接口,需要用户实现。
- net.sf.cglib.proxy.MethodProxy JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用。
CGLIB动态代理的原理就是用Enhancer生成一个原有类的子类,并且设置好callback到proxy, 则原有类的每个方法调用都会转为调用实现了MethodInterceptor接口的proxy的intercept() 函数
实现MethodInterceptor接口
1 | typescript复制代码public class CglibProxy implements MethodInterceptor{ |
被代理对象和测试类
1 | csharp复制代码public class CglibDemo { |
Jdk和Cglib 的区别
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
- 如果目标对象没有实现接口,必须采用CGLIB库.
spring会自动在JDK动态代理和CGLIB之间转换如何强制使用CGLIB实现AOP?
- 添加CGLIB库,SPRING_HOME/cglib/*.jar
- 在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class=”true”/>
JDK动态代理和CGLIB字节码生成的区别? - JDK动态代理只能对实现了接口的类生成代理,而不能针对类
- CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final
【参考文章】
【1】www.cnblogs.com/shijiaqi106…
本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
本文转载自: 掘金