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
图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。
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)。
AopContext
AopContext 提供AOP线程上线文的。
ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");
ProxyConfig
AOP 代理创建的配置类, 提取公共父类保证代理的一致性。
ProxyConfig作为AOP代理创建代理对象的一个基础类,其实现展示了几种代理的实现机制。
BeanFactoryAware+BeanPostProcessor方式
AbstractAdvisingBeanPostProcessor及其子类使用该模式进行框架初始化, 该模式针对特定切面,如Async。通过setBeanFactory方法初始Advisor信息, 并在postProcessAfterInitialization方法中创建代理对象。
AsyncAnnotationBeanPostProcessor
基于SmartInstantiationAwareBeanPostProcessor的AutoProxyCreator
AOP关于AspectJ注解的支持是基于该模式创建, 该模式的特点是: 1. 支持各种不同功能的切面增强。 2. 代理对象负责创建目标对象,支持目标对象的延迟创建。
基于postProcessBeforeInstantiation接口创建。
相关代码见AbstractAutoProxyCreator及其子类, 在Spring AOP创建章节中详细介绍。
初始化核心调用栈示例:
基于FactoryBean模式创建代理
@Transaction及@Cache注解的创建模式
AbstractSingletonProxyFactoryBean
AopProxy
AOP 代理接口实现类包括Cglib和Jdk动态代理
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方法。
流程:
- 获取该方法匹配的Advice
查找匹配实现为接口AdvisorChainFactory接口的实现类:DefaultAdvisorChainFactory。
解析相应的MethodInterceptor接口实现或适配AOP 联盟的语言成为MethodInterceptor接口。
如:MethodBeforeAdviceInterceptor代码如下:
- 执行
- 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