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

前言

咱们若是善用spring框架的源码设计思路,其实能够写出低耦合、高内聚、兼顾灵活性和扩展性较好的优雅代码,尤为是在作框架或组件设计的时候。今天咱们就来分享一个能让咱们代码变得优雅的spring核心模块-AOP模块源码设计。算法

AOP的基本要素

一、切面(Aspect)-----Spring中叫Advisor
切面由切点和加强(引介)组成,它既包括了横切逻辑的定义,也包括了链接点的定义,Spring AOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的链接点中。
二、切点(Pointcut)-----一类JoinPoint的集合
每一个程序类都拥有多个链接点,如一个拥有两个方法的类,这两个方法都是链接点,即链接点是程序类中客观存在的事物。AOP经过“切点”定位特定的链接点。链接点至关于数据库中的记录,而切点至关于查询条件。切点和链接点不是一对一的关系,一个切点能够匹配多个链接点。在Spring中,切点经过org.springframework.aop.Pointcut接口进行描述,它使用类和方法做为链接点的查询条件,Spring AOP的规则解析引擎负责切点所设定的查询条件,找到对应的链接点。其实确切地说,不能称之为查询链接点,由于链接点是方法执行前、执行后等包括方位信息的具体程序执行点,而切点只定位到某个方法上,因此若是但愿定位到具体链接点上,还须要提供方位信息。
三、加强(Advice)-----目标类方法的代理方法实现
加强是织入到目标类链接点上的一段程序代码,在Spring中,加强除用于描述一段程序代码外,还拥有另外一个和链接点相关的信息,这即是执行点的方位。结合执行点方位信息和切点信息,咱们就能够找到特定的链接点。
四、链接点(Joinpoint)-----被拦截的某个目标方法
程序执行的某个特定位置:如类开始初始化前、类初始化后、类某个方法调用前、调用后、方法抛出异常后。一个类或一段程序代码拥有一些具备边界性质的特定点,这些点中的特定点就称为“链接点”。Spring仅支持方法的链接点,即仅能在方法调用前、方法调用后、方法抛出异常时以及方法调用先后这些程序执行点织入加强。链接点由两个信息肯定:第一是用方法表示的程序执行点;第二是用相对点表示的方位。
五、目标对象(Target)
加强逻辑的织入目标类。若是没有AOP,目标业务类须要本身实现全部逻辑,而在AOP的帮助下,目标业务类只实现那些非横切逻辑的程序逻辑,而性能监视和事务管理等这些横切逻辑则可使用AOP动态织入到特定的链接点上。spring

SpringAOP的总体架构

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

AbstractAutoProxyCreator
整个Spring AOP模块的协做组件,它做为AOP的指挥官角色,统一协做Advisor(切面)和AopProxy(动态代理)这两大核心组件。它的本质是BeanPostProcessor(后置处理器)的一种实现,经过Spring IOC模块来启动运行。它针对的主体是Spring的Bean对象。经过扫描有@Aspect注解的类,构建候选的Advisor切面集合;在Aspect注解类中循环查找没有@PointCut注解的方法封装成Advice对象;经过方法上的注解找到对应的PointCut拦截目标,并把Advisor上的表达式封装到PointCut对象中;而后结合当前的Bean对象的元数据,过滤找到有效的Advisor集合。最后经过beanClass建立针对当前bean的动态代理对象;在代理对象中,动态运行Advisor调用链,完成对当前bean中匹配目标的拦截和加强。数据库

一、Advisor切面设计部分
Advisor(切面): 做为AOP中最重要的数据结构,它是aop全部的基础数据的归宿,负责全部的Advice和Pointcut的封装;
PointcutAdvisor:Advisor的扩展组件,它封装Advisor具备的Pointcut能力;
Pointcut(切点):配置Advisor的拦截加强目标,Spring内部最终经过模糊匹配算法,最终定位到具体的拦截目标;
Advice(加强):负责Advisor切面的具体加强业务,它包含AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice、AspectJMethodBeforeAdvice、
AspectJAfterReturningAdvice等具体的加强部件。它们分别一 一对应不一样加强类型Around、After、AfterThrowing、Before、AfterReturning 等;
MethodBeforeAdvice:注解Before加强的顶层设计,最终会统一包装成MethodInterceptor对象,提供统一的链式调用能力;
MethodInterceptor:前三种加强类型的基接口,它扩展的invoke方法让Advisor具备了基础的拦截处理能力;
AfterReturningAdvice:注解AfterReturning加强的顶层设计,最终会统一包装成MethodInterceptor对象,提供统一的链式调用能力;数据结构

二、AopProxy动态代理部分
BeanPostProcessor:全部bean后置处理器的基接口,负责定义基础的前、后置处理行为能力;
SmartInstantiationAwareBeanPostProcessor:继承至BeanPostProcessor基接口,扩展了对bean的属性、引用、类型等处理能力;
ProxyFactory:动态代理工厂接口,负责生产建立指定的AopProxy代理对象;
AopProxy:动态代理的基接口,它扩展了JDK内置的动态代理能力和Cglib类代理能力;
JdkDynamicAopProxy:对JDK内置Proxy动态代理的二次封装;
CglibAopProxy:对cglib类动态加强的二次封装;架构

SpringAOP的源码实现

OK, 有了上面两大块的基础了解后,接下来咱们进入Spring AOP这块的源码。
AOP源码入口
AbstractAutowireCapableBeanFactory.initializeBean()实例化bean完成后的相关后置处理
spring源码解析 - aop相关源码分析
这里是各类BeanPostProcessor后置处理器,针对当前bean作各类扩展和加强的执行入口,包括AbstractAutoProxyCreator、ServletContextAwareProcessor、BootstrapContextAwareProcessor、InitDestroyAnnotationBeanPostProcessor、InstantiationAwareBeanPostProcessorAdapter等。
spring源码解析 - aop相关源码分析
幂等模式,确保一个加强面只作一次
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
对候选的Advisor进行过滤,筛选出做用于当前bean上的相关Advisor,并对最终的Advisor的执行顺序进行排序
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
经过Advisor的准备,对当前bean建立动态拦截代理类
spring源码解析 - aop相关源码分析
在选用代理模式的时候,spring内部采用这种方式:一、当proxyTargetClass为true时,目标bean实现了接口或只有实现类都采用Cglib作动态代理;二、当proxyTargetClass为false时,目标bean若实现了接口则采用JDK内置代理模式, 若目标bean只有实现类,则采用Cglib类代理模式;三、默认proxyTargetClass为false;
spring源码解析 - aop相关源码分析
AbstractAutoProxyCreator.buildAdvisors()封装最终的各类切面对象,为后续的链式调用作准备
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
动态代理对象生成
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
JDK内置代理建立
spring源码解析 - aop相关源码分析
Cglib动态代理建立
spring源码解析 - aop相关源码分析
spring源码解析 - aop相关源码分析
核心加强业务实现
spring源码解析 - aop相关源码分析
bean代理对象中,未被拦截的方法直接反射调用,执行方法
spring源码解析 - aop相关源码分析
ReflectiveMethodInvocation.proceed()链式调用处理核心方法,全部本质AOP的实现(如:注解Transactional、Cacheable和自定义AOP拦截等),都在这里被调用:
spring源码解析 - aop相关源码分析框架

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

总结

以上就是Spring AOP这块的源码分享,从以上的源码咱们不看出几点:1. AOP的本质其实就是指对一类功能加强;2.Spring实现AOP的核心思路是采用动态代理实现;3.全部相似AOP的功能最终都被封装成MethodInterceptor接口,总体的调用链就是递归调用MethodInterceptor.invoke()方法执行相应的拦截处理;4.最后再强调一点,咱们使用AOP的最终目的是解耦业务代码和公共的切面处理逻辑,让整个代码简洁、优雅、职责分明、更易于维护和可读。今天就到暂时这里,更多spring源码相关的干货请继续关注!源码分析

相关文章
相关标签/搜索