一、入口
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 = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//註冊AspectJAwareAdvisorAutoProxyCreator到BeanFactory
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
//優先級設置爲最高
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
- 如果存在"org.springframework.aop.config.internalAutoProxyCreator"的bean並且與當前傳入的類型不同,保留優先級更高的bean
- 如果不存在,註冊當前bean的信息到BeanFactory
b、處理proxy-target-class以及expose-proxy屬性
註冊了AspectJAwareAdvisorAutoProxyCreator後,Spring會接着解析<aop:aspectj-autoproxy>標籤中的proxy-target-class和expose-proxy屬性,如果屬性存在的話,會將屬性值設置到AspectJAwareAdvisorAutoProxyCreator對應的BeanDefinition中:
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if (sourceElement != null) {
//proxy-target-class屬性的處理
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
//expose-proxy屬性的處理
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
下面是設置屬性值的代碼:
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
- proxy-target-class:強制使用CGLib爲目標對象創建代理(如果沒有設置該屬性的話,如果目標對象實現了至少一個接口,則會使用JDK的動態代理)。但是,CGLib的有兩個問題需要考慮:1.無法代理final class,因爲CGLib是通過生成子類來創建代理對象的;2.需要無參構造函數
- expose-proxy:爲了解決目標對象內部的自我調用時,無法實現切面的增強的問題
三、創建AOP代理
1、攔截bean創建
在上一步中,BeanFactory中已經註冊了一個特殊的bean,bean的類型爲 AspectJAwareAdvisorAutoProxyCreator ,該類的繼承結構爲:
AspectJAwareAdvisorAutoProxyCreator實現了BeanPostProcessor接口,所以也就有機會在bean創建過程中爲bean創建代理,接口實現如下:
初始化前調用處理器:
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
postProcessBeforeInitialization方法只是將bean原樣返回,並沒有做任何處理,因此可以看出,AOP代理的bean都是已經初始化好的bean。
初始化後調用處理器:
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
//緩存鍵:1.beanName不爲空的話,使用beanName(FactoryBean會在見面加上"&")
//2.如果beanName爲空,使用Class對象作爲緩存的key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//如果條件符合,則爲bean生成代理對象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//如果已經處理過(targetSourcedBeans存放已經增強過的bean)
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//advisedBeans的key爲cacheKey,value爲boolean類型,表示是否進行過代理
//已經處理過的bean,不需要再次進行處理,節省時間
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//是否是內部基礎設置類Class || 配置了指定bean不需要代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 獲取所有適用的Advisor.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果獲取的增強不爲null,則爲該bean創建代理(DO_NOT_PROXY=null)
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
//標記該cacheKey已經被處理過
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
代碼流程:
- 如果已經處理過,且該bean沒有被代理過,則直接返回該bean
- 如果該bean是內部基礎設置類Class 或 配置了該bean不需要代理,則直接返回bean(返回前標記該bean已被處理過)
- 獲取所有適合該bean的增強Advisor
- 如果增強不爲null,則爲該bean創建代理對象,並返回結果
- 標記該bean已經被處理過
對於需要代理的bean來說,總體有兩個步驟:
- 獲取增強方法或增強器
- 根據獲取結果進行代理
2、是否需要代理
判斷一個bean是否需要代理會經過3次判斷:
- 是否是一個內部基礎設置類
- 是否配置了bean跳過代理
- 是否存在合適的增強器
a、是否是一個內部設施類
判斷一個bean是否是一個內部基礎設置類,由方法isInfrastructureClass提供:
//AnnotationAwareAspectJAutoProxyCreator.class
protected boolean isInfrastructureClass(Class<?> beanClass) {
// 父類判斷是否是內部設置 || 是否是一個Aspect切面
return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));
}
判斷是否是內部設置類交由父類(AspectJAwareAdvisorAutoProxyCreator)判斷,/AnnotationAwareAspectJAutoProxyCreator還增加了一條限制就是Aspect類也無法被增強
AspectJAwareAdvisorAutoProxyCreator實現:
protected boolean isInfrastructureClass(Class<?> beanClass) {
//如果bean繼承自Advice、Pointcut、Advisor、AopInfrastructureBean
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
從上面代碼可以看出,繼承自Advice、Pointcut、Advisor、AopInfrastructureBean無法被增強
isAspect方法實現:
public boolean isAspect(Class<?> clazz) {
//如果bean帶有@Aspect註解,或被Ajc(AspectJ編譯器)編譯
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
綜上,如果一個bean繼承自Advice、Pointcut、Advisor、AopInfrastructureBean 或者 帶有@Aspect註解,或被Ajc(AspectJ編譯器)編譯都會被認定爲內部基礎設置類
b、是否指定bean不被代理
實現方法shouldSkip,實現如下:
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
//獲取所有配置的增強器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
//如果當前beanName與某一個切面名相同則跳過
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
//默認返回false
return super.shouldSkip(beanClass, beanName);
}
shouldSkip會跳過beanName與某一個切面名相同的bean
c、是否存在合適的增強器
如下代碼:
//1.獲取合適的增強器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//2.如果增強器不爲空,則創建代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
Spring會先查找出所有合適的增強器,如果增強器不爲空(null),則表示當前bean需要代理
3、獲取增強器Advisor
獲取增強器的實在位於getAdvicesAndAdvisorsForBean:
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
//獲取合適的增強器
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
//數組爲空,返回null
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//獲取所有的增強器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//增強器中匹配bean
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//模版方法,由子類拓展增強器
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
獲取指定bean的增強方法分爲兩個步驟:
- 獲取所有的增強--findCandidateAdvisors
- 尋找所有增強中使用於bean的增強--findAdvisorsThatCanApply
- 通過模版方法,交由子類拓展增強器
a、獲取所有的增強 findCandidateAdvisors
AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors:
protected List<Advisor> findCandidateAdvisors() {
//調用父類方法加載XML配置文件中聲明的AOP增強
List<Advisor> advisors = super.findCandidateAdvisors();
//獲取所有通過註解添加的AOP增強
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
增強器分類兩類處理:一種是通過<aop>標籤添加的增強,這部分會在解析配置文件的時候添加到Spring容器中,主需要獲取當前容器中Advisor類型的bean就可以獲取到該類增強;另一中是通過註解添加的增強,獲取此類增強還需要對bean進行遍歷解析,下面是解析過程。
BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors:
public List<Advisor> buildAspectJAdvisors() {
//因爲解析會很消耗性能,所以Spring會使用aspectBeanNames保存解析結果
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
//雙重非空判斷,避免再次解析
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
//獲取BeanFactory中Object類型的bean(所有bean)的beanName列表
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
//排除不合法的ban,由子類定義規則,默認返回true
if (!isEligibleBean(beanName)) {
continue;
}
//獲取bean對應類型
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//如果存在@Aspect註解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
//保存bean類型以及@Aspect註解信息
AspectMetadata amd = new AspectMetadata(beanType, beanName);
//檢查@Aspect註解的value值,驗證生成的增強是否是單例
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//獲取標記Aspect註解的增強方法
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
//如果bean是單例,則緩存bean的增強器
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
//bean非單例,只能緩存bean對應的增強器創建工廠
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// 切面創建模式非單例
//如果切面是非單例,但是bean是單例,拋出異常
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
//獲取所有切面
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
/*
如果不是第一次解析切面,證明增強器已經被緩存過了,會執行下面的代碼,查詢緩存
*/
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
上面代碼流程:
- 獲取所有beanName
- 遍歷所有的beanName,篩選出帶有@Aspect註解的bean
- 創建增強
- 解析結果添加到緩存
創建增強器getAdvisors:
對應我們通過@Aspect註解加入的增強來說,最重要的就是將@Before等註解標記的方法轉化爲一個增強器,也就是getAdvisors方法的功能,實現位置爲ReflectiveAspectJAdvisorFactory->getAdvisors:
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//目標Class
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
//代理對象的beanName
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
//對Class上@Aspect註解信息的驗證
validate(aspectClass);
//應用裝飾器模式。將aspectInstanceFactory實例化的增強器緩存起來,避免多次創建
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new LinkedList<Advisor>();
//getAdvisorMethods方法會篩選出不帶有@Pointcut註解的方法
for (Method method : getAdvisorMethods(aspectClass)) {
//創建增強器對象
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
//通過在頭部加入SyntheticInstantiationAdvisor增強器,達到延遲初始化切面bean的目的
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
//對@DeclareParent註解功能的支持
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
方法會遍歷Class中所有不帶有@Pointcut註解的Method對象,並通過該Method對象創建Advisor增強器,getAdvisors:
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
//驗證目標bean的Class對象
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
//獲取方法上的註解信息,並將配置的表達式封裝爲AspectJExpressionPointcut
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
//將Pointcut對象以及Method對象封裝到InstantiationModelAwarePointcutAdvisorImpl類中
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
終於到了Spring對Method封裝的地方,Spring先獲取方法上的AOP註解(如@Before等),並將註解信息封裝到AspectJExpressionPointcut對象中,最後再將Method對象和AspectJExpressionPointcut對象封裝到InstantiationModelAwarePointcutAdvisorImpl類中,組合成爲一個增強器。
AspectJExpressionPointcut對象會解析註解中的表達式,並以此匹配類型和方法以絕對是否進行攔截,並調用增強方法、
b、獲取匹配的增強器
findAdvisorsThatCanApply:
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
//通過一個ThreadLocal變量,設置當前代理的beanName
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//過濾advisors
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
這一步驟主要是環境變量的設置,真正過濾的操作放在了AopUtils.findAdvisorsThatCanApply中:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
for (Advisor candidate : candidateAdvisors) {
//先處理引介增強
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// 引介增強已經處理過了
continue;
}
//對於普通增強器的處理
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
從上面代碼中,可以看到,對增強器進行過濾的函數就是canApply方法:
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
//引介增強是通過設置ClassFilter進行匹配
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
//普通增強器的處理
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
首先獲取Pointcut對象,繼續調用重載的canApply方法:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//1.ClassFilter匹配
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//MethodMatcher的匹配
//如果切點的MethodMatcher類型爲MethodMatcher.TRUE,則表示對所有方法都進行匹配
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
//遍歷接口中所有定義的方法,通過MethodMatcher進行匹配
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
最後是通過ClassFilter已經MethodMatcher匹配目標類包括其實現的接口中定義的方法
c、子類拓展
在獲取增強器的過程中,方法findEligibleAdvisors中調用了一個名爲extendAdvisors的方法,用作子類對已經查找完成的增強器進行拓展,子類AspectJAwareAdvisorAutoProxyCreator進行了實現:
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
該方法會添加一個包含ExposeInvocationInterceptor的增強器到增強器列表頭部。該攔截器將會是第一個被應用的,調用它時會將MethodInvocation放置到ThreadLocal結構中,供其他@Aspect註解對應的增強器使用。它的作用其實就是爲了讓通過@Aspect註解加入的增強器可以訪問到MethodInvocation對象