Spring AOP 源码解析
AOP 即面向切面编程,在前文已经有所介绍,具体的实现方式有以下三种:
- 静态代理:通过为要执行切面操作的类手动定义一个额外的类来完成功能
- 动态代理:在程序运行时动态地生成代理类来实现切面的具体功能
AspectJ
:对 相关的.class
文件进行对应的处理,加入对相关的切点织入一些功能代码来完成
在上述三种实现方式中,静态代理的方式是不会被考虑的,因为这会导致系统代码的耦合,因此主要的实现方式就是动态代理和 AspectJ
一般来讲,使用 AspectJ
来实现 AOP 是最好的解决方案,但是由于 AspectJ
无法被 javac
编译,需要引入额外的编译插件才能完成,因此在 Spring 中对于 AOP 的实现是通过动态代理的方式来实现的
注意,Spring 中对于对象的管理都是以 Bean 的形式来管理的,因此 Spring AOP 相关的类只有在 Spring IOC 中才会有意义
首先回忆一下 Spring IOC 中实例化 Bean 的基本流程:
分析一下实例化 Bean 的流程,可以简单地猜想一下 Spring AOP 的是否是基于 BeanPostProcessor
来实现的?
基于 Proxy Bean 的 AOP
按照代理模式的设计,客户端会直接调用 Proxy 的接口,然后在 Proxy 中由 Proxy 对象完成实际类的接口调用,而在 Proxy 中则定义了一系列的额外操作。这是最简单的 Spring 中最简单的 AOP 实现,下文将以 org.springframework.aop.framework.ProxyFactoryBean
为例来分析对应的源代码。
org.springframework.aop.framework.ProxyFactoryBean
包含的相关属性:
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean
ProxyFactoryBean
的类结构图:
ProxyFactoryBean
只是一个简单的代理对象,并没有使用到类似 AspectJ
来侵入代码的方式来修改对应的对象的源代码,只是起到了一个简单的代理的作用。因此在使用时需要手动获取到这个代理对象才能正常使用 AOP 的功能,这种使用方式和使用 Bean 没有太大的差异,因此在这里不做过多的赘述,具体可以参考 Spring IOC 中有关 Bean 的实例化流程
基于 Auto Proxy 的 AOP基于 Auto Proxy
的 AOP 中已经介绍过了,在此不再做过多的赘述。
实际上,DefaultAdvisorAutoProxyCreator
与 BeanNameAutoProxyCreator
对于 AOP 的实现基本上是相同的,它们之间的主要区别在于 BeanNameAutoProxyCreator
需要自己手动将拦截器 Bean 手动定义到对应的字段属性中,完成 Bean 的装配;而 DefaultAdvisorAutoProxyCreator
则会自动将 BeanFactory
中的 Advisor
类型的 Bean 装载到自己的容器中,相对来讲使用更为简单。它们两者对于 AOP 的实现最终都是通过 AbstractAutoProxyCreator
这个抽象父类来创建代理对象来实现的。
基于 Aspect 的 AOP
基于 Aspect
的 AOP 首先需要进行相关配置以开启 @Aspect
注解的功能,主要有两种方式可以开启 @Aspect
:一时在 XML
配置文件中加入
;二是在一个配置类中加入 @EnableAspectJAutoProxy
注解以开启 @Aspect
解析
对应的源代码:
/**
具体方法定义于 org.springframework.aop.config.AopNamespaceHandler 类中
*/
public void init() {
// In 2.0 XSD as well as in 2.5+ XSDs
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
// 解析 aspectj-autoproxy 配置的内容
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace in 2.5+
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
具体解析的源码位于 org.springframework.aop.config.AspectJAutoProxyBeanDefinitionParser
:
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 核心部分。。。。。
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
registerAspectJAnnotationAutoProxyCreatorIfNecessary
对应的源代码:
// 该方法定义于 org.springframework.aop.config.AopNamespaceUtils 中
public static void
registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 核心部分。。。。
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary
方法对应的源代码:
// 该方法定义于 org.springframework.aop.config.AopConfigUtils 中
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
/**
这里会注册一个 AspectJAwareAdvisorAutoProxyCreator 类型的 Bean
*/
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}
AspectJAwareAdvisorAutoProxyCreator
对应的类继承关系如下:
可以看到,AspectJAwareAdvisorAutoProxyCreator
也是继承自 AbstractAutoProxyCreator
抽象父类,具体已经在 基于 Auto Proxy 的AOP 中详细介绍,在此不做过多的赘述。
AnnotationAwareAspectJAutoProxyCreator
是处理有关 @Aspect
注解的类,它将添加了 AspecJ
注解的 Bean 处理为 Spring 中对应的 Advisor
,具体处理逻辑在此不做详细介绍
参考:
[1] https://javadoop.com/post/spring-aop-source