spring源码解析 – aop相关源码分析

前言

我们如果善用spring框架的源码设计思路,其实可以写出低耦合、高内聚、兼顾灵活性和扩展性较好的优雅代码,尤其是在做框架或组件设计的时候。今天我们就来分享一个 3 I k S H 4能让我们h L k K 3 k S $ D代码变得优雅的sf v J Spring核心模块-AOP模块源码设计。

AOP的基本要素

1、切面(Aspect)-----Spring中叫Advisor
o K * = 1 ^面由切点和增强(引介)组成,它既包括了横切逻辑的定义,也包括了连接点的定义,Spring AOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的 =连接点中。
2、切点(Pointcut)--O ( 5 G 6 Q T p q---一类JoinPoint的集合
每个程序类都拥有多个连接点,如一个拥有两个方法的x e 1 (类,这两个方法都是连接点,即连接点是程序类中客观存在的事物。AO~ w U ? I b E P 2P通过“切点”定位特定的连接点。连接点相当于数据库中的记录,而切7 B L 8点相当于查询条件。切点和连接点不是一对一的关系,一个切点可6 * J e * ! 3 ` *以匹配多个连接点。在Spring中,切点通过org.sG c Cpringframework.aop.Pointcut接口进描述,它使用类和方/ w s Q L } R =法作为连接z X / C q , q , O点的查询条件,Spring AOP的规则解析引擎负责切点所设定的查询条件,找到对应的连接点。其实确切地说,不能称之为查询连接点,因为连接点是方法执行前、执行后等包括方位信息的具体程序执行点,而切点只定位到某个方法上,所以如果希望定位到具体连接点上t 0 A ? x m T @,还需要提供方位信息。
3、增强(Advice)-----目标类方法的代理方法实现
增强是织入到目标类连接点上的一段程序代M . ( W a 码,在Spring中,增强除用于描述一段程序代码外,还拥有另一个和连接点相关的0 w H { , * 6 K `信息,这X J s便是执点的方位。结合执行点方T : ^ J k位信息和切w 9 % H s 2点信息,我们* - ^ Y .就可以找到特定的连接点。
4、连接点(Joinpoint)-----被拦截的某个目标方法
程序执行的某个特定位置:如类开始初始化前、类初始化后、类某个方X Q 9 I 1 q法调用前、调用后、方法抛出异常后。一个类或一段程序代码拥有一些具有边界性质的特定点,这些点中的特定点就称为“连接点”。Spring仅支持方法的连接点,即仅能在方法调用前、方法调用后、方法抛出异常时以f p U X 3 x及方法调用前后这些程序执行点织入增强。连接点由两个信息确定:第一是用方- $ L V ;法表示的程序执行点;第二是用相对点表示的方位T 6 J T ] 8 W W
5、目标对象(Target)
增强逻辑的织入目标类。如果没有AOP,目标业务类P y / a N I { { 3需要自己实现所有逻辑,而在AOP的帮助下,目标业务类只实现那些非横切逻辑的程序逻辑,而性: - k = $ / ( { A能监视和事务管理等这些横切逻辑则可以使用AOP动态织入到特定的连接点上。

SpringAOP的整体架构

spring源码解析 - aop相关源码分析

AbstractAutoProxyCreator
整个Spring AOP模块的协作组件,它作为AOR h 2P的指挥官角色,统一协作Advisor(切面)和AopPro+ + V F G exy(动态代理)这两大核心组件。它的本质是BeanPostProcessor(后置处理器)的一种实现,通过Spring IOC模块来启动运行。它针对的主体是Spring的Bean对象。通过扫描有@Aspect注解的类,构建候l c = I选的Advisor切面集合;在Aspecu R yt注解类中循环查找没有@PointCut注解的方法封装成Advice对象;通过方法上的注解找到对应的PointCut拦截目标Y d o d w ) ~,并把Advisor上的表达式封装到PointCut对象中;然后结合当前的Beav W e rn对象的元数据,过滤找到有效的Advis- j S K 1 I # ( hor集合。最后] N B # 3 _通过beanClass创建针对当前bean的动态代理对象;在代理对象中,动态运行Advisor调用链,完成对当前bean中匹配目标的拦截和增强。

1、Advisor切面 G + Q : C L X设计部分
Advisor(切面): 作为AOP中最重要的数据结, ] K h / D构,它是aop所有Y X 2 ~ / k 4 $的基础数_ H } ^据的归宿,负责所有的Advice和Pointcut的封装;
PointcutAdvisor:Advisor的扩展组件,它封6 = S ( Q h 7 S装Advisor具有的Pointcut能力;
Pointcut(切点):配置Advisor的拦截增强目标,Spring内部最终通过模糊匹配算法,最终定. X V G ` i ! 0 D位到具体的拦截目标;
AdviP . L m Q cce(增强):负H = s D -责Advisor切面的具体增强业务,它包含AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterT; D b % ? - W 8hrowingAdvice、AspectJMethodBeforeAdvice{ v H 4
AspectJAfterReturningAdvice等具体的增强部件。它o T # l b $ 4 w们分别一 一对应不同增强类型Around、After、AfterThrowing、Before、A* 3 ; b ^ ZfterReturning 等;
MethodBeforeAdvice:注解Before增强的顶层设计,最终会统一包装成MethodInterceptor对象,提供统一的链式调用能力;
MethodInterceptor:前三种增强类型的基接口,它扩展的invoke方法让Am / K x 2 1dvisor具有了基础的拦截处理能力;
AfterReturningAdvice:注解n L 5 b / | - 3AfterReturning增强的顶层设计g - ],最终会统一包装成MethodInterceptor对象,提供e : $ O z ?统一的链W T R式调用能力;

2、AopProxy动态代理部分
BeanPostProcessor:所有bean后置处理器的基接口,负责定义基础的前、后置处理行为能力;
SmartInstantiationAwareBeanPostProcessob h ]r:继承至BeanPostP, + 5 j Q 2 h 8rocessor基接口,扩展了对bean的属性、i 3 ! ( l引用、类型等处理能力;
ProxyFactorD _ * { r T }y:动态代理L - P 0 & K d 9工厂接口,负责生l ) p 2 r产创建指定的AopProxy代理对象;
AopPrm $ @ soxy:动态代理的基接口,它扩展了J* X S % [ T n - jDK内置的动态代理能力和Cglib类代理能力A I o m 1z ! _
JdkDynamicAopProxy:对JDK内置Proxy动态代理的二次封装;
CglibAopProxy:对cgli1 _ A e ] 7b类动态增强的二次封装;

SpringAOP的n 1 U t *源码实现

OK, 有了上面两大块的基础了解- v H ^ S [ *后,接下来我们进入SprH r Cing AOP这块的源码。
AOP源码入口
AbstractAutowireCapableBeanFactory.initializeBean()实例化be] d ` W z o Uan完成后的相关后置处理
spring源码解析 - aop相关源码分析
这里是各种BeanPostProcessor后置处理器,针对当前beanr J ~ E o C [ ; M做各种扩展和增U { (强的执行入口,包括AbstractAutoProxyCreator、ServletContextAwareProcessor、BootstrapContextAwareProcessor、InitDestroyAnnotationBeanPostProcessor、InstantiationAwareBeanPostProcessorAdapter等。
spring源码解析 - aop相关源码分析
幂等5 E R ` e 4模式,确保一个增强面只做一次
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
对候选的Advisor进行过滤,筛选出作用于当前bean上的相关Advisor,并对最终的Advisor的执行顺序进行排序
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
通过Advisor的准备,对当前bean创建动态拦截代理类
spring源码解析 - aop相关源码分析
在选用9 ` t 9 G代理模式的时候,spring内部采用这种方式:1、E l F X d * (当proxyTargetClass为true时,目标bean实现了接* T S b口或只有实现类都采用Cglib做动态代理;2、当proxyTargetClass为f$ x # [ $ Z a ;al) 2 @se时,目标bean若实现了接口则采用JDK内置w e ? [ &代理模式, 若目标bean只有实现类,则采用Cglib类代理模式;3、默认proxyTargetClass为false;
spring源码解析 - aop相关源码分析
AbstractAutoProB J & E { J T =xyCreator.buildAdvisors()封装最终的各种切面对象,为后续的链式调用做准备
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
动态代理对象生成
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
JDK内置代理c u F ) H h J创建
spring源码解析 - aop相关源码分析
CgliL @ c F b动态代理创建
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
核心增强业务实现
spring源码解析 - aop相关源码分析
bean代理对象中,未被S ] v D A =拦截的方法直接反射调用,u z Z X O 7执行方法
spring源码解析 - aop相关源码分析
ReflectiveMethodInvocation.proceed()链式调用处理核心方法,所有本质AOP的实现(如:注解Transactional、Cach@ C m | oeable和自定义AOP拦截等),都在这里被调用:
spring源码解析 - aop相关源码分析

注:本文侧重点是分享S[ 7 &pring AOP在源码上的实现,对于使用层面的东西不是本文的重点 ~

总结

以上就是Spring AOP这块的源码分4 9 ; z } h享,从以~ 1 = c [ :上的源码我们不看出几点:1. AOP的本质其实就是指对一类功能增强;2.Spring实现AOP的核心思路是采用动态代理实现;3.所有类似AOP的功能最终都被封装成} I }Mets t ? l 8 EhodInterceptor接口,整体的调用链就是递归调用MethodIntercepto n por.invoke()方法执行相应的拦截处理;4.最后再强调一点,我们使用AOP的最终目的是D / $解耦业务代码和公共的切面处理逻辑,让整个代码简洁、优雅、职责分明、更易于` W ( /维护和可读。今天就到暂时这里,更多spring源码相关的干货请继续关注!