Spring AOP 详解

AOP基础

AOP: Aspect Oriented Program, 面向切面编程。解耦(组织结构调整)、增强(扩展)。

AOP术语

AOP Aliance

AOP Aliance: AOP联盟,定义了AOP的基础规范。

AOP JavaAPIDoc 网址: Generated Documentation (Untitled)

AOP 官方白皮书地址:https://aopalliance.sourceforge.net/white_paper/white_paper.pdf

Spring AOP 详解及@Trasactional-LMLPHP

图1 Spring AOP中的AOP Aliance 基本接口

AspectJ

AsprctJ 是Java社区里最完整最流行的AOP框架。

官网: AspectJ Documentation | The Eclipse Foundation

AspectJ提供了完整的AOP解决方案,支持以下三种织入时机:

  • compile-time:编译期织入,编译出包含织入代码的 .class 文件
  • post-compile:编译后织入,增强已经编译出来的类,如我们要增强依赖的 jar 包中的某个类的某个方法
  • load-time:在 JVM 进行类加载的时候进行织入

Spring AOP 和 AspectJ

Spring AOP: 为Spring IoC上提供的AOP实现,应用于Spring Bean容器管理的,以及Spring 框架其他技术,如Spring Transactional

AspectJ: 提供完整的AOP解决方案。它比Spring AOP更强大,但也更复杂。还值得注意的是,AspectJ可以应用于所有域对象。

Spring AOP代理的生成

Cglib代理和JDK动态代理。

JDK 动态代理是JDK内置的动态代理工具,底层原理是反射机制,为目标接口创建代理,动态代理类需要实现InvocationHandler接口。代理实现原理是通过实现被代理类的接口,被代理对象由InvocationHandler进行包装调用。

Cglib底层原理通过字节码处理框架ASM修改类的字节码生成继承方法的子类,通过修改字节码生成子类代理直接代替实体类,需要实现MethodInterceptor接口。 继承方式意味着不能对final修饰的类、final修饰的方法、私有方法进行代理。

Spring AOP 创建代理过程

下面介绍了Spring Aop支持AspectJ注解的代理创建过程, 其他注解的AOP类似,只是通过不同的扩展点来创建代理对象,如ProxyFactoryBean或BeanPostProcessor。

@EnableAspectJAutoProxy

项目为启用AspectJ的Spring-AOP,通常会再配置文件中加上@EnableAspectJAutoProxy

@Import(AspectJAutoProxyRegistrar.class)

@Import 注解包含一个实现了ImportBeanDefinitionRegistrar的类, 注册重要的Bean用于后续Bean初始化。AspectJAutoProxyRegistrar

AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator负责创建AOP代理,实现了SmartInstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor) 接口,核心创建逻辑在postProcessBeforeInstantiation实现中。

检查是否该创建Bean对象的逻辑在AopUtils.canApply方法。

AopProxyFactory

继续跟进代码 最终由AopProxyFactory来创建。 AopProxyFactory 调用AopProxy接口的getProxy方法创建代理对象。 AopProxy有两个实现:JdkDynamicAopProxy和ObjenesisCglibAopProxy对应于JDK动态代理和Cglib代理实现。

选择AopProxy的代码如下:

具体创建代理的代码为Cglib和JDK代理的使用方法。如JdkDynamicAopProxy的getProxy()代码如下:

Spring AOP切面相关抽象及解析过程

主要抽象
Advice

Org.aopalliance.aop.Advice: AOP联盟的Advice接口,代表增强入口,其实现包括Interceptors或其他任何类型的Advice。

Spring AOP 详解及@Trasactional-LMLPHP

Org.aopalliance.intercept.interceptor: : 指可以针对Joint事件进行拦截的拦截器。

MethodInterceptor:对接口调用的拦截

ConstructorInterceptor: 对对象构造的拦截

DynamicIntroductionAdvice:支持在Advice上实现附加接口。

IntroductionInterceptor extends MethodInterceptor, DynamicIntroductionAdvice : 通过Interceptor实现DynamicIntroductionAdvice。

       IntroductionInfo: 描述引入接口的信息

MethodBeforeAdvice: 在方法调用之前执行的Advice

AfterReturningAdvice: 在方法返回之后执行的Advice

ThrowsAdvice: 异常抛出后执行的Advice

       public void afterThrowing(Exception ex)

       public void afterThrowing(RemoteException)

       public void afterThrowing(Method method, Object[] args, Object target, Exception ex)

       public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)

ClassFilter

ClassFilter: 负责检查一个pointcut 或则 introduction时候和目标类匹配

MethodMatcher

MethodMatcher:负责检查方法是否匹配Advice

Advisor

Advisor: 持有AOP Advice信息的接口,

AdvisorChainFactory

实现类DefaultAdvisorChainFactory,接口方法getInterceptorsAndDynamicInterceptionAdvice返回指定方法的Advice链(增强链),当执行代理对象时根据这里放回的Advice链进行增强。

Advised

Advised是AOP的配置信息, AOP代理的创建时基于Advised提供的Advise及Advisor信息创建。

如:Advised接口提供了Advisor的管理方法(get/addAdvisors)。

Spring AOP 详解及@Trasactional-LMLPHP

AopContext

AopContext 提供AOP线程上线文的。

ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");

ProxyConfig

AOP 代理创建的配置类, 提取公共父类保证代理的一致性。

ProxyConfig作为AOP代理创建代理对象的一个基础类,其实现展示了几种代理的实现机制。

BeanFactoryAware+BeanPostProcessor方式

AbstractAdvisingBeanPostProcessor及其子类使用该模式进行框架初始化, 该模式针对特定切面,如Async。通过setBeanFactory方法初始Advisor信息, 并在postProcessAfterInitialization方法中创建代理对象。

Spring AOP 详解及@Trasactional-LMLPHP

AsyncAnnotationBeanPostProcessor

基于SmartInstantiationAwareBeanPostProcessor的AutoProxyCreator

AOP关于AspectJ注解的支持是基于该模式创建, 该模式的特点是: 1. 支持各种不同功能的切面增强。 2. 代理对象负责创建目标对象,支持目标对象的延迟创建。

基于postProcessBeforeInstantiation接口创建。

相关代码见AbstractAutoProxyCreator及其子类, 在Spring AOP创建章节中详细介绍。

初始化核心调用栈示例:

基于FactoryBean模式创建代理

@Transaction及@Cache注解的创建模式

Spring AOP 详解及@Trasactional-LMLPHP

AbstractSingletonProxyFactoryBean

AopProxy

AOP 代理接口实现类包括Cglib和Jdk动态代理

Spring AOP 详解及@Trasactional-LMLPHP      

AopProxyFactory

AopProxy工厂接口,负责创建AopProxy对象。实现类是DefaultAopProxyFactory

注解信息的解析(Advised对象的创建)

Advised对象的解析过程同ProxyConfig章节介绍的代理对象过程类似,同样是三种模式的解析过程。

AbstractAdvisingBeanPostProcessor

AbstractAdvisingBeanPostProcessor 针对特定注解创建代理对象模式。扩展点BeanPostProcessor 的postProcessAfterInitialization方法中检查注解是否作用在Bean上,如是则创建代理。

AbstractSingletonProxyFactoryBean

基于FactoryBean机制,对通过XML配置的FactoryBean,针对目标Bean解析所得Advicsed对象。

ProxyFactoryBean

基于ProxyFactoryBean创建的代理的对象,在获取对象时会检查是否需要解析和创建AOP 的代理。

Spring AOP的执行

JDK代理执行代码

JdkDynamicAopProxy 执行了JDK动态代理的InvocationHandler接口, 执行入口就是JdkDynamicAopProxy的invoke方法。

流程:

  1. 获取该方法匹配的Advice

查找匹配实现为接口AdvisorChainFactory接口的实现类:DefaultAdvisorChainFactory。

解析相应的MethodInterceptor接口实现或适配AOP 联盟的语言成为MethodInterceptor接口。

Spring AOP 详解及@Trasactional-LMLPHP

如:MethodBeforeAdviceInterceptor代码如下:

  1. 执行
  1. ReflectiveMethodInvocation 处理方法

AopContext

AopContext类可以再代理类执行过程中获取到代理对象, 通过代理对象可以保证基于AOP增强的特性得到执行,从而解决直接this.xxx调用直接执行被代理对象的方法,造成增强实效。

Spring Aop 应用-@Transactional

       Spring Transaction就是基于Spring AOP机制实现的事务。

解析@Transactionnal

       事务的拦截逻辑实现主要在TransactionInterceptor类中, 如果通过XML文件配置的TransactionProxyFactoryBean创建代理对象,则在FactoryBean的afterProperties方法中创建Advisor生成proxyFactory对象(见上面章节)。

对于基于注解的Transaction注解解析在于TransactionAttributeSourcePointcut由AOP框架触发解析判断某个方法是否满足Transactional注解。

解析逻辑代码如下:

TransactionInterceptor

事务执行逻辑实现与TransactionInterceptor

10-09 15:49