前言
上文介紹了 AOP 的基本概念,本文開始進入 AOP 的源碼解析,本文仍以 AspectJ 來進行介紹,首先是 AOP 註解的解析。
正文
當使用 <aop:aspectj-autoproxy /> 註解開啓 AOP 功能時。
Spring會從“META-INF/spring.handlers” 配置文件中拿到該註解對應的 NamespaceHandlerSupport:AopNamespaceHandler
在 AopNamespaceHandler 的 init 方法會給該註解註冊對應的解析器,aspectj-autoproxy 對應的解析器是:AspectJAutoProxyBeanDefinitionParser。
@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());
}
我們知道,當解析到 <aop:aspectj-autoproxy /> 註解時,會調用 AspectJAutoProxyBeanDefinitionParser 的 parse方法。
關於自定義註解的解析內容之前 IoC 的文章介紹過了,如果不瞭解的可以參考:Spring IoC:parseCustomElement 詳解
AspectJAutoProxyBeanDefinitionParser#parse
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 1.註冊AspectJAnnotationAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 2.對於註解中子節點的處理
extendBeanDefinition(element, parserContext);
return null;
}
1.註冊 AspectJAnnotationAutoProxyCreator,見代碼塊1。
代碼塊1:AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 1.註冊AspectJAnnotationAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 2.對於proxy-target-class以及expose-proxy屬性的處理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 3.註冊組件並通知,便於監聽器做進一步處理
registerComponentIfNecessary(beanDefinition, parserContext);
}
1.註冊 AspectJAnnotationAutoProxyCreator,見代碼塊2。
2.對於 proxy-target-class 以及 expose-proxy 屬性的處理,見代碼塊3。
代碼塊2:AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 1.如果註冊表中已經存在beanName=org.springframework.aop.config.internalAutoProxyCreator的bean,則按優先級進行選擇。
// beanName=org.springframework.aop.config.internalAutoProxyCreator,可能存在的beanClass有三種,按優先級排序如下:
// InfrastructureAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// 拿到已經存在的bean定義
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 如果已經存在的bean的className與當前要註冊的bean的className不相同,則按優先級進行選擇
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 拿到已經存在的bean的優先級
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
// 拿到當前要註冊的bean的優先級
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
// 如果當前要註冊的bean的優先級大於已經存在的bean的優先級,則將bean的className替換爲當前要註冊的bean的className,
apcDefinition.setBeanClassName(cls.getName());
}
// 如果小於,則不做處理
}
// 如果已經存在的bean的className與當前要註冊的bean的className相同,則無需進行任何處理
return null;
}
// 2.如果註冊表中還不存在,則新建一個Bean定義,並添加到註冊表中
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
// 設置了order爲最高優先級
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 註冊BeanDefinition,beanName爲org.springframework.aop.config.internalAutoProxyCreator
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
org.springframework.aop.config.internalAutoProxyCreator 是內部管理的自動代理創建者的 bean 名稱,可能對應的 beanClassName 有三種,對應的註解如下:
InfrastructureAdvisorAutoProxyCreator:<tx:annotation-driven />
AspectJAwareAdvisorAutoProxyCreator:<aop:config />
AnnotationAwareAspectJAutoProxyCreator:<aop:aspectj-autoproxy />
當同時存在多個註解時,會使用優先級最高的 beanClassName 來作爲 org.springframework.aop.config.internalAutoProxyCreator 的 beanClassName。本系列文章暫不考慮同時存在其他註解的情況,所以在這邊會註冊的 beanClassName 爲:AnnotationAwareAspectJAutoProxyCreator。
代碼塊3:useClassProxyingIfNecessary
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if (sourceElement != null) {
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
// 如果節點設置了proxy-target-class=true,則給beanName爲org.springframework.aop.config.internalAutoProxyCreator
// 的BeanDefinition添加proxyTargetClass=true的屬性,之後創建代理的時候將強制使用Cglib代理
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
// 如果節點設置了expose-proxy=true,則給beanName爲org.springframework.aop.config.internalAutoProxyCreator
// 的BeanDefinition添加exposeProxy=true的屬性,之後創建攔截器時會根據該屬性選擇是否暴露代理類
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
總結
本文的內容比較簡單,最重要的內容就是註冊了內部管理的自動代理創建者的 bean:AnnotationAwareAspectJAutoProxyCreator,AOP 的大部分重要內容都在這個bean 裏,之後會一一介紹。