吃透动态代理,解密spring AOP源码(四)

前面讲到了动态代理的底层原理,接下来咱们来看一下aop的动态代理.
Spring AOP使用了两种代理机制:一种是基于JDK的动态代理,一种是基于CGLib的动态代理.spring

①JDK动态代理:使用JDK建立代理有一个限制,它只能为接口建立代理实例.这一点能够从Proxy的接口方法
newProxyInstance(ClassLoader loader,Class [] interfaces,InvocarionHandler h)中看的很清楚
第二个入参 interfaces就是须要代理实例实现的接口列表.
②CGLib:采用底层的字节码技术,能够为一个类建立子类,在子类中采用方法拦截的技术拦截全部父类方法的调用
并顺势织入横切逻辑.
③对比:CGLib所建立的动态代理对象的性能比JDK的高大概10倍,但CGLib在建立代理对象的时间比JDK大概多8倍,因此对于singleton的代理对象或者具备实例池的代理,由于无需重复的建立代理对象,因此比较适合CGLib动态代理技术,反之选择JDK代理。值得一提的是因为CGLib采用动态建立子类的方式生成代理对象,因此不能对目标类中final的方法进行代理。性能

可是这种实现方式存在三个明显须要改进的地方:this

a.目标类的全部方法都添加了横切逻辑,而有时,这并非咱们所指望的,咱们可能只但愿对业务类中的某些特定的方法添加横切逻辑;编码

b.咱们经过硬编码的方式制定了织入横切逻辑的织入点,即在目标业务方法的开始和结束前织入代码spa

c.咱们手工编写代理实例的建立过程,为不一样类建立代理时,须要分别编写相应的建立代码,没法作到通用;debug

还有一个问题是:spring依赖注入时,何时会建立代理类,有时候是cglib有时候是jdkproxy有时候只是普通实例,有兴趣的能够查阅资料,getBean依赖注入过程,可查看IOC源码。代理

下面咱们举个例子看看aop事务注解是怎么实现的。
JDK动态代理:aop中生成的代理类是JdkDynamicAopProxy子类,debug调试的时候能够看到,打开源码可看到实现了AopProxy和invocationHandler也就实现invoke方法。
invoke关键代码:调试

// Get the interception chain for this method.加载一系列的拦截器
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

TransactionInterceptor是事务拦截器,全部带有@Transactional注解的方法都会通过拦截器invoke方法拦截,点进方法里面能够发现代码以下:code

clipboard.png

好比回滚方法点进去发现是获取事务管理器而后回滚对象

clipboard.png

最后看下静态代理,JDK动态代理及cglib动态代理的对比

clipboard.png

相关文章
相关标签/搜索