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, BeanClassLoaderAware, BeanFactoryAware {
    // 省略一部分不太重要的代码
    
    /**
    	生成的 Proxy 对象要实现的接口,当访问时将会直接调用 Proxy 的相关实现
    */
    public void setProxyInterfaces(Class<?>[] proxyInterfaces) throws ClassNotFoundException {
		setInterfaces(proxyInterfaces);
	}
    
    /* 
    	设置要代理的接口的具体实现,对应代理模式中的 RealSubject 具体类对象,
    	具体可以参考有关 JDK 动态代理的内容
    */
    public void setTarget(Object target) {
		setTargetSource(new SingletonTargetSource(target));
	}
    
    /**
    	设置拦截器,具体来讲就是对应的切面
    */
    public void setInterceptorNames(String... interceptorNames) {
		this.interceptorNames = interceptorNames;
	}
}

ProxyFactoryBean 的类结构图:

ProxyFactoryBean.png

ProxyFactoryBean 只是一个简单的代理对象,并没有使用到类似 AspectJ 来侵入代码的方式来修改对应的对象的源代码,只是起到了一个简单的代理的作用。因此在使用时需要手动获取到这个代理对象才能正常使用 AOP 的功能,这种使用方式和使用 Bean 没有太大的差异,因此在这里不做过多的赘述,具体可以参考 Spring IOC 中有关 Bean 的实例化流程

基于 Auto Proxy 的 AOP基于 Auto Proxy 的 AOP 中已经介绍过了,在此不再做过多的赘述。

实际上,DefaultAdvisorAutoProxyCreatorBeanNameAutoProxyCreator 对于 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.png

可以看到,AspectJAwareAdvisorAutoProxyCreator 也是继承自 AbstractAutoProxyCreator 抽象父类,具体已经在 基于 Auto Proxy 的AOP  中详细介绍,在此不做过多的赘述。

AnnotationAwareAspectJAutoProxyCreator 是处理有关 @Aspect 注解的类,它将添加了 AspecJ 注解的 Bean 处理为 Spring 中对应的 Advisor,具体处理逻辑在此不做详细介绍


参考:

[1] https://javadoop.com/post/spring-aop-source