该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读。
Spring 版本:5.1.14.RELEASE
在开始阅读 Spring AOP 源码之前,需要对 Spring IoC 有一定的了解,可查看我的 《死磕Spring之IoC篇 - 文章导读》 这一系列文章
了解 AOP 相关术语,可先查看 《Spring AOP 常见面试题) 》 这篇文章
该系列其他文章请查看:《死磕 Spring 之 AOP 篇 - 文章导读》
通过前面关于 Spring AOP 的所有文章,我们对 Spring AOP 的整个 AOP 实现逻辑进行了比较详细的分析,例如 Spring AOP 的自动代理,JDK 动态代理或 CGLIB 动态代理两种方式创建的代理对象的拦截处理过程等内容都有讲到。本文将会分析 Spring AOP 的注解驱动,如何引入 AOP 模块,包括如何处理 Spring AOP 的 XML 配置。
在 Spring AOP 中可以通过 @EnableAspectJAutoProxy 注解驱动整个 AOP 模块,我们先一起来看看这个注解。
org.springframework.context.annotation.EnableAspectJAutoProxy,开启 Spring AOP 整个模块的注解
/**
 * @since 3.1
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	/**
	 * 是否开启类代理,也就是是否开启 CGLIB 动态代理
	 */
	boolean proxyTargetClass() default false;
	/**
	 * 是否需要暴露代理对象
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;
}
该注解上面有一个 @Import 注解,它的 value 是 AspectJAutoProxyRegistrar.class 类。
这里先讲一下 @Import 注解的原理,在 Spring IoC 初始化完 BeanFactory 后会有一个 BeanDefinitionRegistryPostProcessor 对其进行后置处理,对配置类(例如 @Configuration 注解标注的 Bean)进行处理,如果这个 BeanDefinition 包含 @Import 注解,则获取注解的值,进行下面的处理:
String[] selectImports(AnnotationMetadata) 方法获取需要导入的 Bean 的名称 registerBeanDefinitions(AnnotationMetadata, BeanDefinitionRegistry) 方法,支持注册相关 Bean关于 @Import 注解不熟悉的小伙伴查看我的另一篇 《死磕Spring之IoC篇 - @Bean 等注解的实现原理》 文章
所以说 @EnableAspectJAutoProxy 注解需要标注在能够被 Spring 扫描的类上面,例如 @Configuration 标注的类。其中 AspectJAutoProxyRegistrar 就是 ImportBeanDefinitionRegistrar 的实现类,我们一起来看看。
org.springframework.context.annotation.AspectJAutoProxyRegistrar,在 @EnableAspectJAutoProxy 注解中被导入
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		// <1> 注册一个 AnnotationAwareAspectJAutoProxyCreator 自动代理对象(如果没有注册的话),设置为优先级最高
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		// <2> 获取 @EnableAspectJAutoProxy 注解的配置信息
		AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		// <3> 如果注解配置信息不为空,则根据配置设置 AnnotationAwareAspectJAutoProxyCreator 的属性
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				// 设置 `proxyTargetClass` 为 `true`(开启类代理,也就是开启 CGLIB 动态代理)
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				// 设置 `exposeProxy` 为 `true`(需要暴露代理对象,也就是在 Advice 或者被拦截的方法中可以通过 AopContext 获取代理对象)
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
}
可以看到它注册 BeanDefinition 的过程如下:
AopConfigUtils 注册一个 AnnotationAwareAspectJAutoProxyCreator 自动代理对象(如果没有注册的话),设置为优先级最高@EnableAspectJAutoProxy 注解的配置信息AnnotationAwareAspectJAutoProxyCreator 的属性
proxyTargetClass 为 true,则进行设置(开启类代理,也就是开启 CGLIB 动态代理)exposeProxy 为 true,则进行设置(需要暴露代理对象,也就是在 Advice 或者被拦截的方法中可以通过 AopContext 获取代理对象)可以看到会注册一个 AnnotationAwareAspectJAutoProxyCreator 自动代理对象,是不是很熟悉,就是在前面文章讲到的自动代理对象,那么就开启了 Spring AOP 自动代理,也就是开启了 Spring AOP 整个模块。
org.springframework.aop.config.AopConfigUtils,AOP 工具类
public abstract class AopConfigUtils {
	/**
	 * The bean name of the internally managed auto-proxy creator.
	 */
	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";
	/**
	 * Stores the auto proxy creator classes in escalation order.
	 */
	private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
	static {
		// Set up the escalation list...
		APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
	}
}
上面定义了 AspectJAwareAdvisorAutoProxyCreator 几种子类的优先级,排在后面优先级越高
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, @Nullable Object source) {
    // 注册 AnnotationAwareAspectJAutoProxyCreator Bean
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
        Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    // <1> 如果 `org.springframework.aop.config.internalAutoProxyCreator` 已注册
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        // <1.1> 获取对应的 BeanDefinition 对象
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        // <1.2> 如果已注册的 `internalAutoProxyCreator` 和入参的 Class 不相等,说明可能是继承关系
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            // <1.2.1> 获取已注册的 `internalAutoProxyCreator` 的优先级
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            // <1.2.2> 获取需要注册的 `internalAutoProxyCreator` 的优先级
            int requiredPriority = findPriorityForClass(cls);
            // InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator
            // 三者都是 AbstractAutoProxyCreator 自动代理对象的子类
            if (currentPriority < requiredPriority) {
                // <1.2.3> 如果需要注册的优先级更高,那取代已注册的 Class 对象
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        // <1.3> 因为已注册,则返回 `null`
        return null;
    }
    // <2> 没有注册,则创建一个 RootBeanDefinition 对象进行注册
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    // <3> 设置来源
    beanDefinition.setSource(source);
    // <4> 设置为最高优先级
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    // <5> 设置角色为**ROLE_INFRASTRUCTURE**,表示是 Spring 框架内部的 Bean
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // <6> 注册自动代理的 Bean,名称为 `org.springframework.aop.config.internalAutoProxyCreator`
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    // <7> 返回刚注册的 RootBeanDefinition 对象
    return beanDefinition;
}
可以看到会注册一个 AnnotationAwareAspectJAutoProxyCreator 自动代理 Bean,过程如下:
org.springframework.aop.config.internalAutoProxyCreator 已注册
internalAutoProxyCreator 和入参的 Class 不相等,说明可能是继承关系
internalAutoProxyCreator 的优先级internalAutoProxyCreator 的优先级InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreatornullorg.springframework.aop.config.internalAutoProxyCreator整个过程很简单,如果已注册自动代理对象,则判断当前需要注册的是否优先级更高,如果更高则修改其对应的 Class 名称;如果没有注册,那么注册这个代理对象,设置优先级最高。
再开始之前对于 Spring XML 配置文件不熟悉的小伙伴可以看看我的 《死磕Spring之IoC篇 - 解析自定义标签(XML 文件)》 这篇文章。在 Spring 中对于非默认命名空间的标签需要通过指定的 NamespaceHandler 来处理,在 Spring 的 XML 配置文件中都是在 <beans /> 标签内定义数据,需要指定 http://www.springframework.org/schema/beans 作为命名空间,那么对于 http://www.springframework.org/schema/aop 就需要指定 NamespaceHandler 来处理。我们来看到 spring-aop 模块下的 META-INF/spring.handlers 配置文件:
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
Spring AOP 相关的标签需要 AopNamespaceHandler 进行处理
org.springframework.aop.config.AopNamespaceHandler,继承 NamespaceHandlerSupport 抽象类,Spring AOP 命名空间下的标签处理器
public class AopNamespaceHandler extends NamespaceHandlerSupport {
	/**
	 * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
	 * ‘{@code config}‘, ‘{@code spring-configured}‘, ‘{@code aspectj-autoproxy}‘
	 * and ‘{@code scoped-proxy}‘ tags.
	 */
	@Override
	public void init() {
		// In 2.0 XSD as well as in 2.1 XSD.
		// <aop:config /> 标签的解析器
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		// <aop:aspectj-autoproxy /> 标签的解析器
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		// <aop:scoped-proxy /> 标签的解析器
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
		// Only in 2.0 XSD: moved to context namespace as of 2.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}
}
public abstract class NamespaceHandlerSupport implements NamespaceHandler {
	private final Map<String, BeanDefinitionParser> parsers = new HashMap<>();
    
    private final Map<String, BeanDefinitionDecorator> decorators = new HashMap<>();
    
    protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
        this.parsers.put(elementName, parser);
    }
    
    protected final void registerBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator dec) {
		this.decorators.put(elementName, dec);
	}
}
在这个 NamespaceHandler 的 init() 初始化方法中,会往 parsers 中注册几个标签解析器或者装饰器:
<aop:config />:ConfigBeanDefinitionParser<aop:aspectj-autoproxy />:AspectJAutoProxyBeanDefinitionParser<aop:scoped-proxy />:ScopedProxyBeanDefinitionDecorator继续看到 NamespaceHandlerSupport 这个方法:
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    // <1> 获得元素对应的 BeanDefinitionParser 对象
    BeanDefinitionParser parser = findParserForElement(element, parserContext);
    // <2> 执行解析
    return (parser != null ? parser.parse(element, parserContext) : null);
}
@Nullable
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    // 获得元素名
    String localName = parserContext.getDelegate().getLocalName(element);
    // 获得 BeanDefinitionParser 对象
    BeanDefinitionParser parser = this.parsers.get(localName);
    if (parser == null) {
        parserContext.getReaderContext().fatal(
                "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
    }
    return parser;
}
@Override
@Nullable
public BeanDefinitionHolder decorate(
        Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
    // 根据标签名获取 BeanDefinitionDecorator 对象
    BeanDefinitionDecorator decorator = findDecoratorForNode(node, parserContext);
    return (decorator != null ? decorator.decorate(node, definition, parserContext) : null);
}
@Nullable
private BeanDefinitionDecorator findDecoratorForNode(Node node, ParserContext parserContext) {
    BeanDefinitionDecorator decorator = null;
    // 获得元素名
    String localName = parserContext.getDelegate().getLocalName(node);
    if (node instanceof Element) {
        decorator = this.decorators.get(localName);
    }
    else if (node instanceof Attr) {
        decorator = this.attributeDecorators.get(localName);
    }
    else {
        parserContext.getReaderContext().fatal(
                "Cannot decorate based on Nodes of type [" + node.getClass().getName() + "]", node);
    }
    if (decorator == null) {
        parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionDecorator for " +
                (node instanceof Element ? "element" : "attribute") + " [" + localName + "]", node);
    }
    return decorator;
}
会根据标签名称找到对应的 BeanDefinitionParser 解析器进行解析,那么现在思路清晰了,上面不同的标签对应着不同的 BeanDefinitionParser 或者 BeanDefinitionDecorator,我们来看看是怎么处理的。
<beans>
    <aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="false" />
</beans>
这个标签的作用和 @EnableAspectJAutoProxy 注解相同,开启整个 Spring AOP 模块,原理也相同,注册一个 AnnotationAwareAspectJAutoProxyCreator 自动代理对象
org.springframework.aop.config.AspectJAutoProxyBeanDefinitionParser,<aop:aspectj-autoproxy /> 标签对应 BeanDefinitionParse 解析器
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		// 解析 <aop:aspectj-autoproxy /> 标签
		// 注册 AnnotationAwareAspectJAutoProxyCreator 自动代理对象(如果没有注册的话),设置为优先级最高
		// 过程和 @EnableAspectJAutoProxy
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
		// 解析 <aop:include /> 子标签,用于指定需要开启代理的路径
		extendBeanDefinition(element, parserContext);
		return null;
	}
	private void extendBeanDefinition(Element element, ParserContext parserContext) {
		BeanDefinition beanDef = parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
		if (element.hasChildNodes()) {
			addIncludePatterns(element, parserContext, beanDef);
		}
	}
	private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
		ManagedList<TypedStringValue> includePatterns = new ManagedList<>();
		NodeList childNodes = element.getChildNodes();
		for (int i = 0; i < childNodes.getLength(); i++) {
			Node node = childNodes.item(i);
			if (node instanceof Element) {
				Element includeElement = (Element) node;
				TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
				valueHolder.setSource(parserContext.extractSource(includeElement));
				includePatterns.add(valueHolder);
			}
		}
		if (!includePatterns.isEmpty()) {
			includePatterns.setSource(parserContext.extractSource(element));
			beanDef.getPropertyValues().add("includePatterns", includePatterns);
		}
	}
}
<aop:aspectj-autoproxy /> 标签的解析过程先通过 AopNamespaceUtils 工具类注册一个 AnnotationAwareAspectJAutoProxyCreator 自动代理对象,然后继续解析 <aop:include /> 子标签,用于指定需要开启代理的路径
org.springframework.aop.config.AopNamespaceUtils,Spring AOP XML 配置文件解析工具类
public abstract class AopNamespaceUtils {
	public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";
	private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";
	public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
		// <1> 注册 AnnotationAwareAspectJAutoProxyCreator 自动代理对象(如果没有注册的话),设置为优先级最高
		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		// <2> 则根据 <aop:aspectj-autoproxy /> 标签的配置设置 AnnotationAwareAspectJAutoProxyCreator 的属性
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		// <3> 将注册的 BeanDefinition 也放入 `parserContext` 上下文中
		registerComponentIfNecessary(beanDefinition, parserContext);
	}
	private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
		// 如果 <aop:aspectj-autoproxy /> 标签不为空
		if (sourceElement != null) {
			boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
			if (proxyTargetClass) {
				// 设置 `proxyTargetClass` 为 `true`(开启类代理,也就是开启 CGLIB 动态代理)
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
			if (exposeProxy) {
				// 设置 `exposeProxy` 为 `true`(需要暴露代理对象,也就是在 Advice 或者被拦截的方法中可以通过 AopContext 获取代理对象)
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
	private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
		if (beanDefinition != null) {
			parserContext.registerComponent(
					new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
		}
	}
}
注册 AnnotationAwareAspectJAutoProxyCreator 自动代理对象的过程和 @EnableAspectJAutoProxy 注解类型,这里不再做讲述
<beans>
    <bean id="echoService" class="org.geekbang.thinking.in.spring.aop.overview.DefaultEchoService" >
    	<aop:scoped-proxy />
	</bean>
</beans>
<aop:scoped-proxy /> 标签需要定义在 <bean /> 中,用来装饰这个 Bean,会生成一个 ScopedProxyFactoryBean 类型的 RootBeanDefinition 对象并注册。ScopedProxyFactoryBean 是一个 FactoryBean,在其 getObject() 方法中返回的是一个代理对象。也就是说 <aop:scoped-proxy /> 标签可以将一个 Bean 进行 AOP 代理。
org.springframework.aop.config.ScopedProxyBeanDefinitionDecorator,<aop:scoped-proxy /> 标签对应的 BeanDefinitionDecorator 装饰器
class ScopedProxyBeanDefinitionDecorator implements BeanDefinitionDecorator {
	private static final String PROXY_TARGET_CLASS = "proxy-target-class";
	@Override
	public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
		boolean proxyTargetClass = true;
		if (node instanceof Element) {
			Element ele = (Element) node;
			if (ele.hasAttribute(PROXY_TARGET_CLASS)) {
				proxyTargetClass = Boolean.valueOf(ele.getAttribute(PROXY_TARGET_CLASS));
			}
		}
		// Register the original bean definition as it will be referenced by the scoped proxy
		// and is relevant for tooling (validation, navigation).
		// 创建一个 ScopedProxyFactoryBean 类型的 RootBeanDefinition 对象并注册
		// ScopedProxyFactoryBean 用于装饰 `definition`,进行 AOP 代理
		BeanDefinitionHolder holder = ScopedProxyUtils.createScopedProxy(definition, parserContext.getRegistry(), proxyTargetClass);
		String targetBeanName = ScopedProxyUtils.getTargetBeanName(definition.getBeanName());
		parserContext.getReaderContext().fireComponentRegistered(
				new BeanComponentDefinition(definition.getBeanDefinition(), targetBeanName));
		return holder;
	}
}
<beans>
    <aop:aspectj-autoproxy/>
    <bean id="aspectXmlConfig" class="org.geekbang.thinking.in.spring.aop.features.aspect.AspectXmlConfig"/>
    <aop:config>
        <aop:pointcut id="anyPublicStringMethod" expression="execution(public String *(..))"/>
        <aop:advisor advice-ref="echoServiceMethodInterceptor" pointcut-ref="anyPublicStringMethod" />
        <aop:aspect id="AspectXmlConfig" ref="aspectXmlConfig">
            <aop:pointcut id="anyPublicMethod" expression="execution(public * *(..))"/>
            <aop:around method="aroundAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
            <aop:before method="beforeAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
            <aop:before method="beforeAnyPublicMethod" pointcut="execution(public * *(..))"/>
            <aop:after method="finalizeAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
            <aop:after-returning method="afterAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
            <aop:after-throwing method="afterThrowingAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
        </aop:aspect>
    </aop:config>
</beans>
<aop:config> 标签内可以定义 AspectJ 切面的相关信息,例如 Pointcut、Advisor 和 Advice;同时也会注册一个 Spring AOP 自动代理对象(如果有必要的话),不过 是注册 AspectJAwareAdvisorAutoProxyCreator,只能解析处理 Spring IoC 中 Advisor 类型的 Bean,无法解析 @AspectJ 等相关注解,所以我们最好使用 <aop:aspectj-autoproxy/> 标签来驱动 Spring AOP 模块。
org.springframework.aop.config.ConfigBeanDefinitionParser,<aop:config /> 标签对应的 BeanDefinitionParser 解析器,我们来看到它的 parse(..) 方法
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
    parserContext.pushContainingComponent(compositeDef);
    // <1> 解析 <aop:config /> 标签
    // 注册 AspectJAwareAdvisorAutoProxyCreator 自动代理对象(如果需要的话),设置为优先级最高
    // 过程和 @EnableAspectJAutoProxy、<aop:aspectj-autoproxy /> 差不多
    configureAutoProxyCreator(parserContext, element);
    // <2> 获取 <aop:config /> 的子标签,遍历进行处理
    List<Element> childElts = DomUtils.getChildElements(element);
    for (Element elt: childElts) {
        // 获取子标签的名称
        String localName = parserContext.getDelegate().getLocalName(elt);
        if (POINTCUT.equals(localName)) {
            // <2.1> 处理 <aop:pointcut /> 子标签,解析出 AspectJExpressionPointcut 对象并注册
            parsePointcut(elt, parserContext);
        }
        else if (ADVISOR.equals(localName)) {
            // <2.2> 处理 <aop:advisor /> 子标签,解析出 DefaultBeanFactoryPointcutAdvisor 对象并注册,了指定 Advice 和 Pointcut(如果有)
            parseAdvisor(elt, parserContext);
        }
        else if (ASPECT.equals(localName)) {
            // <2.3> 处理 <aop:aspectj /> 子标签,解析出所有的 AspectJPointcutAdvisor 对象并注册,里面包含了 Advice 对象和对应的 Pointcut 对象
            // 同时存在 Pointcut 配置,也会解析出 AspectJExpressionPointcut 对象并注册
            parseAspect(elt, parserContext);
        }
    }
    // <3> 将 `parserContext` 上下文中已注册的 BeanDefinition 合并到上面 `compositeDef` 中(暂时忽略)
    parserContext.popAndRegisterContainingComponent();
    return null;
}
该方法的处理过程如下:
解析 <aop:config /> 标签,注册 AspectJAwareAdvisorAutoProxyCreator 自动代理对象(如果需要的话),设置为优先级最高
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
    // 注册 AspectJAwareAdvisorAutoProxyCreator 自动代理对象(如果需要的话)
    AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}
过程和 @EnableAspectJAutoProxy、<aop:aspectj-autoproxy /> 的解析过程差不多,这里不再进行展述
获取 <aop:config /> 的子标签,遍历进行处理
parsePointcut(..) 方法,处理 <aop:pointcut /> 子标签,解析出 AspectJExpressionPointcut 对象并注册parseAdvisor(..) 方法,处理 <aop:advisor /> 子标签,解析出 DefaultBeanFactoryPointcutAdvisor 对象并注册,了指定 Advice 和 Pointcut(如果有)parseAspect(..) 方法,处理 <aop:aspectj /> 子标签,解析出所有的 AspectJPointcutAdvisor 对象并注册,里面包含了 Advice 对象和对应的 Pointcut 对象;同时存在 Pointcut 配置,也会解析出 AspectJExpressionPointcut 对象并注册我们依次来看看你上面三种子标签的处理过程
<beans>
    <aop:aspectj-autoproxy/>
    <bean id="aspectXmlConfig" class="org.geekbang.thinking.in.spring.aop.features.aspect.AspectXmlConfig"/>
    <aop:config>
        <aop:pointcut id="anyPublicStringMethod" expression="execution(public String *(..))"/>
    </aop:config>
</beans>
处理过程在 parsePointcut(..) 方法中,如下:
// ConfigBeanDefinitionParser.java
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
    // <1> 获取 <aop:pointcut /> 标签的 `id` 和 `expression` 配置
    String id = pointcutElement.getAttribute(ID);
    String expression = pointcutElement.getAttribute(EXPRESSION);
    AbstractBeanDefinition pointcutDefinition = null;
    try {
        this.parseState.push(new PointcutEntry(id));
        // <2> 创建一个 AspectJExpressionPointcut 类型的 RootBeanDefinition 对象
        pointcutDefinition = createPointcutDefinition(expression);
        // <3> 设置来源
        pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
        String pointcutBeanName = id;
        // <4> 注册这个 AspectJExpressionPointcut 对象
        if (StringUtils.hasText(pointcutBeanName)) {
            // <4.1> 如果 `id` 配置不为空,则取其作为名称
            parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
        }
        else {
            // <4.2> 否则,自动生成名称,也就是取 `className`
            pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
        }
        // <5> 将注册的 BeanDefinition 包装成 ComponentDefinition 放入 `parserContext` 上下文中,暂时忽略
        parserContext.registerComponent(
                new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
    }
    finally {
        this.parseState.pop();
    }
    return pointcutDefinition;
}
解析过程大致如下:
获取 <aop:pointcut /> 标签的 id 和 expression 配置
根据 expression 表达式创建一个 AspectJExpressionPointcut 类型的 RootBeanDefinition 对象,如下:
protected AbstractBeanDefinition createPointcutDefinition(String expression) {
    // <1> 创建一个 AspectJExpressionPointcut 类型的 RootBeanDefinition 对象
    RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
    // <2> 设置为原型模式,需要保证每次获取到的 Pointcut 对象都是新的,防止在某些地方被修改而影响到其他地方
    beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
    // <3> 设置为是 Spring 内部合成的
    beanDefinition.setSynthetic(true);
    // <4> 添加 `expression` 属性值
    beanDefinition.getPropertyValues().add(EXPRESSION, expression);
    // <5> 返回刚创建的 RootBeanDefinition 对象
    return beanDefinition;
}
设置来源
注册这个 AspectJExpressionPointcut 对象
id 配置不为空,则取其作为名称className将注册的 BeanDefinition 包装成 ComponentDefinition 放入 parserContext 上下文中,暂时忽略
<beans>
    <aop:aspectj-autoproxy/>
    <bean id="aspectXmlConfig" class="org.geekbang.thinking.in.spring.aop.features.aspect.AspectXmlConfig"/>
    <aop:config>
        <aop:pointcut id="anyPublicStringMethod" expression="execution(public String *(..))"/>
        <aop:advisor advice-ref="echoServiceMethodInterceptor" pointcut-ref="anyPublicStringMethod" />
    </aop:config>
</beans>
处理过程在 parseAdvisor(..) 方法中,如下:
// ConfigBeanDefinitionParser.java
private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
    // <1> 解析 <aop:advisor /> 标签
    // 创建一个 DefaultBeanFactoryPointcutAdvisor 类型的 RootBeanDefinition 对象,并指定了 Advice
    AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
    // <2> 获取 `id` 属性
    String id = advisorElement.getAttribute(ID);
    try {
        this.parseState.push(new AdvisorEntry(id));
        String advisorBeanName = id;
        // <3> 注册第 `1` 步创建的 RootBeanDefinition
        if (StringUtils.hasText(advisorBeanName)) {
            // <3.1> 如果 `id` 不为空,则取其作为名称
            parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef);
        }
        else {
            // <3.2> 否则,生成一个名称,也就是 `className`
            advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
        }
        // <4> 获取这个 Advisor 对应的 Pointcut(也许就是一个 AspectJExpressionPointcut,也可能是引用的 Pointcut 的名称)
        Object pointcut = parsePointcutProperty(advisorElement, parserContext);
        // <4.1> 如果是 AspectJExpressionPointcut
        if (pointcut instanceof BeanDefinition) {
            // 第 `1` 步创建的 RootBeanDefinition 添加 `pointcut` 属性,指向这个 AspectJExpressionPointcut
            advisorDef.getPropertyValues().add(POINTCUT, pointcut);
            parserContext.registerComponent(
                    new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
        }
        // <4.2> 否则,如果是一个引用的 Pointcut 的名称
        else if (pointcut instanceof String) {
            // 第 `1` 步创建的 RootBeanDefinition 添加 `pointcut` 属性,指向这个名称对应的引用
            advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
            parserContext.registerComponent(
                    new AdvisorComponentDefinition(advisorBeanName, advisorDef));
        }
    }
    finally {
        this.parseState.pop();
    }
}
解析过程大致如下:
解析 <aop:advisor /> 标签,创建一个 DefaultBeanFactoryPointcutAdvisor 类型的 RootBeanDefinition 对象,并指定了 Advice
private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) {
    // <1> 创建一个 DefaultBeanFactoryPointcutAdvisor 类型的 RootBeanDefinition 对象
    RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
    // <2> 设置来源
    advisorDefinition.setSource(parserContext.extractSource(advisorElement));
    // <3> 获取 `advice-ref` 属性配置,必须配置一个对应的 Advice
    String adviceRef = advisorElement.getAttribute(ADVICE_REF);
    if (!StringUtils.hasText(adviceRef)) {
        parserContext.getReaderContext().error(
                "‘advice-ref‘ attribute contains empty value.", advisorElement, this.parseState.snapshot());
    }
    else {
        // <4> 将 `advice-ref` 添加至 `adviceBeanName` 属性,也就是指向这个 Advice 引用
        advisorDefinition.getPropertyValues().add(
                ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef));
    }
    // <5> 根据 `order` 配置为 RootBeanDefinition 设置优先级
    if (advisorElement.hasAttribute(ORDER_PROPERTY)) {
        advisorDefinition.getPropertyValues().add(
                ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY));
    }
    // <6> 返回刚创建的 RootBeanDefinition
    return advisorDefinition;
}
获取 id 属性
注册第 1 步创建的 RootBeanDefinition
id 不为空,则取其作为名称className获取这个 Advisor 对应的 Pointcut(也许就是一个 AspectJExpressionPointcut,也可能是引用的 Pointcut 的名称)
1 步创建的 RootBeanDefinition 添加 pointcut 属性,指向这个 AspectJExpressionPointcut1 步创建的 RootBeanDefinition 添加 pointcut 属性,指向这个名称对应的引用<beans>
    <aop:aspectj-autoproxy/>
    <bean id="aspectXmlConfig" class="org.geekbang.thinking.in.spring.aop.features.aspect.AspectXmlConfig"/>
    <aop:config>
        <aop:aspect id="AspectXmlConfig" ref="aspectXmlConfig">
            <aop:pointcut id="anyPublicMethod" expression="execution(public * *(..))"/>
            <aop:around method="aroundAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
            <aop:before method="beforeAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
            <aop:before method="beforeAnyPublicMethod" pointcut="execution(public * *(..))"/>
            <aop:after method="finalizeAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
            <aop:after-returning method="afterAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
            <aop:after-throwing method="afterThrowingAnyPublicMethod" pointcut-ref="anyPublicMethod"/>
        </aop:aspect>
    </aop:config>
</beans>
处理过程在 parseAspect(..) 方法中,如下:
private void parseAspect(Element aspectElement, ParserContext parserContext) {
    // <1> 获取 `id` 和 `ref` 属性
    String aspectId = aspectElement.getAttribute(ID);
    String aspectName = aspectElement.getAttribute(REF);
    try {
        this.parseState.push(new AspectEntry(aspectId, aspectName));
        // <2> 定义两个集合 `beanDefinitions`、`beanReferences`
        // 解析出来的 BeanDefinition
        List<BeanDefinition> beanDefinitions = new ArrayList<>();
        // 需要引用的 Bean
        List<BeanReference> beanReferences = new ArrayList<>();
        // <3> 获取所有的 <aop:declare-parents /> 子标签,遍历进行处理
        List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
        for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
            Element declareParentsElement = declareParents.get(i);
            // <3.1> 解析 <aop:declare-parents /> 子标签
            // 解析出 DeclareParentsAdvisor 对象,添加至 `beanDefinitions`
            beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
        }
        // We have to parse "advice" and all the advice kinds in one loop, to get the
        // ordering semantics right.
        // <4> 获取 <aop:aspectj /> 所有的子节点,遍历进行处理
        NodeList nodeList = aspectElement.getChildNodes();
        boolean adviceFoundAlready = false;
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            // <4.1> 如果是 <aop:around />、<aop:before />、<aop:after />、<aop:after-returning />、<aop:after-throwing /> 标签,则进行处理
            if (isAdviceNode(node, parserContext)) {
                // <4.2> 如果第一次进来,那么就是配置了 Advice,则 `ref` 必须指定一个 Bean,因为这些 Advice 的 `method` 需要从这个 Bean 中获取
                if (!adviceFoundAlready) {
                    adviceFoundAlready = true;
                    if (!StringUtils.hasText(aspectName)) {
                        parserContext.getReaderContext().error(
                                "<aspect> tag needs aspect bean reference via ‘ref‘ attribute when declaring advices.",
                                aspectElement, this.parseState.snapshot());
                        return;
                    }
                    // <4.2.1> 往 `beanReferences` 添加需要引用的 Bean
                    beanReferences.add(new RuntimeBeanReference(aspectName));
                }
                // <4.3> 根据 Advice 标签进行解析
                // 创建一个 AspectJPointcutAdvisor 对象,里面包含了 Advice 对象和对应的 Pointcut 对象,并进行注册
                AbstractBeanDefinition advisorDefinition = parseAdvice(
                        aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
                // <4.4> 添加至 `beanDefinitions` 中
                beanDefinitions.add(advisorDefinition);
            }
        }
        // <5> 将上面创建的所有 Advisor 和引用对象都封装到 AspectComponentDefinition 对象中
        // 并放入 `parserContext` 上下文中,暂时忽略
        AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
                aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
        parserContext.pushContainingComponent(aspectComponentDefinition);
        // <6> 获取所有的 <aop:pointcut /> 子标签,进行遍历处理
        List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
        for (Element pointcutElement : pointcuts) {
            // <6.1> 解析出 AspectJExpressionPointcut 对象并注册
            parsePointcut(pointcutElement, parserContext);
        }
        parserContext.popAndRegisterContainingComponent();
    } finally {
        this.parseState.pop();
    }
}
解析过程大致如下:
id 和 ref 属性beanDefinitions、beanReferences,分别保存解析出来的 BeanDefinition 和需要引用的 Bean<aop:declare-parents /> 子标签,遍历进行处理
<aop:declare-parents /> 子标签,解析出 DeclareParentsAdvisor 对象并注册,添加至 beanDefinitions<aop:aspectj /> 所有的子节点,遍历进行处理
<aop:around />、<aop:before />、<aop:after />、<aop:after-returning />、<aop:after-throwing /> 标签,则进行处理ref 必须指定一个 Bean,因为这些 Advice 的 method 需要从这个 Bean 中获取
beanReferences 添加需要引用的 BeanbeanDefinitions 中parserContext 上下文中,暂时忽略<aop:pointcut /> 子标签,进行遍历处理
上面第 4.3 会解析相关 Advice 标签,我们一起来看看
private AbstractBeanDefinition parseAdvice(
        String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
        List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
    try {
        this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));
        // create the method factory bean
        // <1> 创建 MethodLocatingFactoryBean 类型的 RootBeanDefinition
        // 因为通过标签配置的 Advice 对应的方法在其他 Bean 中,那么可以借助于 FactoryBean 来进行创建
        RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
        // <1.1> 获取 `targetBeanName` 和 `method` 并进行设置
        methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
        methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
        // <1.2> 设置这个 Bean 是由 Spring 内部合成的
        methodDefinition.setSynthetic(true);
        // create instance factory definition
        // <2> 创建一个 SimpleBeanFactoryAwareAspectInstanceFactory 类型的 RootBeanDefinition
        RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
        // <2.1> 设置了 AspectJ 对应的 名称,用于获取这个 AspectJ 的实例对象
        aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
        // <2.2> 设置这个 Bean 是由 Spring 内部合成的
        aspectFactoryDef.setSynthetic(true);
        // register the pointcut
        // <3> 创建一个 Advice 对象,包含了对应的 Pointcut
        AbstractBeanDefinition adviceDef = createAdviceDefinition(
                adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
                beanDefinitions, beanReferences);
        // configure the advisor
        // <4> 创建一个 AspectJPointcutAdvisor 类型的 RootBeanDefinition 对象,用于包装上面创建的 Advice
        // Spring AOP 中的 Advice 都是放入 Advisor “容器” 中
        RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
        // <4.1> 设置来源
        advisorDefinition.setSource(parserContext.extractSource(adviceElement));
        // <4.2> 将上面创建的 Advice 对象作为构造器入参
        advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
        // <4.3> 设置 `order` 优先级
        if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
            advisorDefinition.getPropertyValues().add(
                    ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
        }
        // register the final advisor
        // <5> 注册这个 AspectJPointcutAdvisor,自动生成名字
        parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
        // <6> 返回这个已注册的 AspectJPointcutAdvisor
        return advisorDefinition;
    }
    finally {
        this.parseState.pop();
    }
}
处理过程大致如下:
创建 MethodLocatingFactoryBean 类型的 RootBeanDefinition,因为通过标签配置的 Advice 对应的方法在其他 Bean 中,那么可以借助于 FactoryBean 来进行创建
targetBeanName 和 method 并进行设置创建一个 SimpleBeanFactoryAwareAspectInstanceFactory 类型的 RootBeanDefinition
创建一个 Advice 对象,包含了对应的 Pointcut
private AbstractBeanDefinition createAdviceDefinition(
        Element adviceElement, ParserContext parserContext, String aspectName, int order,
        RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
        List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
    // <1> 根据 Advice 标签创建对应的 Advice
    // <aop:before /> -> AspectJMethodBeforeAdvice
    // <aop:after /> -> AspectJAfterAdvice
    // <aop:after-returning /> -> AspectJAfterReturningAdvice
    // <aop:after-throwing /> -> AspectJAfterThrowingAdvice
    // <aop:around /> -> AspectJAroundAdvice
    RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
    // <1.1> 设置来源
    adviceDefinition.setSource(parserContext.extractSource(adviceElement));
    // <1.2> 设置引用的 AspectJ 的名称
    adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
    // <1.3> 设置优先级
    adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
    if (adviceElement.hasAttribute(RETURNING)) {
        adviceDefinition.getPropertyValues().add(
                RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
    }
    if (adviceElement.hasAttribute(THROWING)) {
        adviceDefinition.getPropertyValues().add(
                THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
    }
    if (adviceElement.hasAttribute(ARG_NAMES)) {
        adviceDefinition.getPropertyValues().add(
                ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
    }
    // <2> 获取 Advice 的构造器参数对象 `cav`
    // 设置 1. 引用的方法、2. Pointcut(也许是引用的 Pointcut 的名称)、3. 引用的方法所属 AspectJ 对象
    // 你点进这些 Advice 类型的对象中看看构造方法就知道怎么回事,例如:AspectJMethodBeforeAdvice
    ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
    // <2.1> 往 `cav` 添加 Advice 对应的方法作为入参
    cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
    // <2.2> 解析出对应的 Pointcut 对象(可能是一个 AspectJExpressionPointcut,也可能是引用的 Pointcut 的一个运行时引用对象)
    Object pointcut = parsePointcutProperty(adviceElement, parserContext);
    // <2.2.1> 如果是 AspectJExpressionPointcut
    if (pointcut instanceof BeanDefinition) {
        // 往 `cav` 添加 `pointcut` 入参
        cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
        // 添加至 `beanDefinitions`
        beanDefinitions.add((BeanDefinition) pointcut);
    }
    // <2.2.2> 否则,如果是 引用的 Pointcut
    else if (pointcut instanceof String) {
        // 根据引用的 Pointcut 的名称生成一个引用对象
        RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
        // 往构 `cav` 添加 `pointcut` 入参
        cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
        // 添加至 `pointcutRef`
        beanReferences.add(pointcutRef);
    }
    // <2.3> 往 `cav` 添加 Advice 对应的方法所在 Bean 作为入参
    cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);
    // <3> 返回为 Advice 创建的 RootBeanDefinition 对象
    return adviceDefinition;
}
private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) {
    String elementName = parserContext.getDelegate().getLocalName(adviceElement);
    if (BEFORE.equals(elementName)) {
        return AspectJMethodBeforeAdvice.class;
    }
    else if (AFTER.equals(elementName)) {
        return AspectJAfterAdvice.class;
    }
    else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
        return AspectJAfterReturningAdvice.class;
    }
    else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
        return AspectJAfterThrowingAdvice.class;
    }
    else if (AROUND.equals(elementName)) {
        return AspectJAroundAdvice.class;
    }
    else {
        throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
    }
}
创建一个 AspectJPointcutAdvisor 类型的 RootBeanDefinition 对象,用于包装上面创建的 Advice,Spring AOP 中的 Advice 都是放入 Advisor “容器” 中
注册这个 AspectJPointcutAdvisor,自动生成名字
返回这个已注册的 AspectJPointcutAdvisor
在 Spring Boot 中使用 Spring AOP 我们通常会这样进行 Maven 引入:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.3.5.RELEASE</version>
</dependency>
上面这个依赖内部会引入这样两个依赖:
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>5.2.10.RELEASE</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.6</version>
  <scope>compile</scope>
</dependency>
引入相关依赖后,同样可以使用 @EnableAspectJAutoProxy 注解来驱动整个 Spring AOP 依赖,不过在 Spring AOP 中你不需要显示地使用这个注解,因为在 spring-boot-autoconfigure 中,有一个 AOP 自动配置类,我们一起来看看
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,Spring Boot 中的 AOP 自动配置类
@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
	@Configuration
	@EnableAspectJAutoProxy(proxyTargetClass = false)
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
	public static class JdkDynamicAutoProxyConfiguration {
	}
	@Configuration
	@EnableAspectJAutoProxy(proxyTargetClass = true)
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
	public static class CglibAutoProxyConfiguration {
	}
}
可以看到这个 @Configuration 配置类中有两个条件注解,都是基于 @Conditional 扩展的注解,如下:
@ConditionalOnClass 注解:value 中的所有 Class 对象在当前 JVM 必须存在才会注入当前配置类;
因为你通过 Spring Boot 引入了 aspectjweaver 这个包,Aspect、Advice 和 AnnotatedElement 三个 Class 对象也就存在了,而 EnableAspectJAutoProxy 这个注解本身就存在 Spring 中,所以这个注解是满足条件的
@ConditionalOnProperty 注解:指定的配置为 true 才会注入当前配置类
这个注解会判断 spring.aop.auto 是否为 true,没有配置默认为 true,所以这个注解也是满足条件的
所以得到的结论就是,当你引入 spring-boot-starter-aop 依赖后,Spring Boot 中会注入 AopAutoConfiguration 这个配置类,在这个配置类中的静态内部类使用了 @EnableAspectJAutoProxy 这个注解,那么也就会注册 Spring AOP 自动代理对象。
通过本文,我们可以知道 @EnableAspectJAutoProxy 这个模块驱动注解会借助 @Import 注解注册一个 AnnotationAwareAspectJAutoProxyCreator 自动代理对象,也就开启了 Spring AOP 自动代理,驱动了整个 Spring AOP 模块。
除了注解的方式,Spring 一样也支持 <aop:aspectj-autoproxy /> XML 配置的方式注册一个自动代理对象,驱动整个 Spring AOP 模块;也有 <aop:scoped-proxy /> 标签支持装饰某个 Bean,使其进行 AOP 代理。当然,Spring 也支持 <aop:config /> 标签配置 AspectJ 切面的相关内容,包括 Poincut、Advice 和 Advisor 等配置。
同时,在使用 Spring Boot 中引入 spring-boot-starter-aop 依赖后,不需要显示地使用 @EnableAspectJAutoProxy 注解来开启 Spring AOP 的自动代理,因为在 spring-boot-autoconfigure 中,有一个 AopAutoConfiguration 自动配置类,会使用这个注解驱动了整个 Spring AOP 模块。
死磕Spring之AOP篇 - Spring AOP注解驱动与XML配置
原文:https://www.cnblogs.com/lifullmoon/p/14654886.html