一、入口
AOP的Jar包如下如所示:
META-INF中是Spring自定义标签的配置文件,对<aop>标签的支持
spring.schemas配置如下,作用是定义<aop>标签的内容(根据不同版本,Spring使用不同的xsd文件来描述):
http\://www.springframework.org/schema/aop/spring-aop-2.0.xsd=org/springframework/aop/config/spring-aop-2.0.xsd
http\://www.springframework.org/schema/aop/spring-aop-2.5.xsd=org/springframework/aop/config/spring-aop-2.5.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.0.xsd=org/springframework/aop/config/spring-aop-3.0.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.1.xsd=org/springframework/aop/config/spring-aop-3.1.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.2.xsd=org/springframework/aop/config/spring-aop-3.2.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.0.xsd=org/springframework/aop/config/spring-aop-4.0.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.1.xsd=org/springframework/aop/config/spring-aop-4.1.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.2.xsd=org/springframework/aop/config/spring-aop-4.2.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.3.xsd=org/springframework/aop/config/spring-aop-4.3.xsd
http\://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-4.3.xsd
spring.handles中配置只有一行,如下所示:
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
配置的入口便是AopNamespaceHandler。它的定义如下:
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* 注册几个BeanDefinitionParser,用来支持config、spring-configured、aspectj-autoproxy、scoped-proxy标签的功能
*/
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
二、AspectJAutoProxyBeanDefinitionParser注册AOP组件
在平时使用Spring AOP基于注解配置AOP的时候,配置文件中都需要加入下面这行配置来开启AOP:
<!--开启字段AOP代理-->
<aop:aspectj-autoproxy/>
对应到前面的代码中,Spring就会使用AspectJAutoProxyBeanDefinitionParser来解析这行配置:
public BeanDefinition parse(Element element, ParserContext parserContext) {
//注册AspectJAnnotationAutoProxyCreator(具体实现类是AnnotationAwareAspectJAutoProxyCreator)
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
//对于注解中子类的处理
extendBeanDefinition(element, parserContext);
return null;
}
代码中重点是registerAspectJAnnotationAutoProxyCreatorIfNecessary方法,该方法会注册AnnotationAwareAspectJAutoProxyCreator:
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//注册beanName为"org.springframework.aop.config.internalAutoProxyCreator"的bean,如果bean为null的话
//bean的类型为AspectJAwareAdvisorAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//对于proxy-target-class以及expose-proxy属性的处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//注册组件并通知,便于监听器进一步处理
registerComponentIfNecessary(beanDefinition, parserContext);
}
a、注册AspectJAwareAdvisorAutoProxyCreator
AopConfigUtil.registerAspectJAnnotationAutoProxyCreatorIfNecessary方法实现中,会直接将AspectJAwareAdvisorAutoProxyCreator注册到BeanFactory中:
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}
下面是注册(或升级)的源码实现:
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//如果已经存在beanName为"org.springframework.aop.config.internalAutoProxyCreator"的bean并且与当前传入的类型不同,
//则比较两个bean的优先级,保留优先级高的那个
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClas