Spring(十七)Spring AOP 原理探究-aop解析入口分析

上一篇文章主要介紹了Spring AOP一些簡單用法,當然如果要了解更多,可以選擇再去看看Spring 文檔。
博主還是喜歡從源碼中知其所以然嘿嘿。

spring-boot-starter-aop

博主以 Spring-boot-starter-aop 爲例,開始分析。
spring boot 中使用 aop,我們只需要引入 spring-boot-starter-aop 即可定義註解進行操作:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.1.7.RELEASE</version>
        </dependency>

spring-boot-starter-aop 反編譯後的依賴來看,這個項目裏面並沒有任何代碼:
在這裏插入圖片描述
沒有任何代碼,那麼裏面是怎麼引入的呢?抱着這個想法,博主下載了Spring Boot項目源碼查看,不過裏面確實沒有java代碼,只有一個gradle依賴。

dependencies {
	api(platform(project(":spring-boot-project:spring-boot-dependencies")))
	api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter"))
	api("org.springframework:spring-aop")
	api("org.aspectj:aspectjweaver")
}

spring-boot-starter-aop 項目中,引入了一些依賴,包括 spring-aopajpectjweaver,以及當前spring-boot項目的starter

經過前面文章也有個大概瞭解,spring-aop項目中應該只是一些類,而沒有注入到Spring 容器中,那麼 spring-aop 的引線在哪裏呢?

首先要使用spring-boot-starter-aop,首先得是一個spring-boot架構項目,而 spring-boot項目引入依賴的一個途徑是通過增加Spring SPI配置文件: spring.factories,有加載 @EnableAutoConfiguration 進行加載,但很明顯,spring-boot-starter-aop 不屬於這一類。

在針對 @SpringBootApplication 進行更細緻分析,它在 spring-boot-autoconfigure 包下面:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}

上面 SpringBootApplication 註解中,使用 @ComponentScan 對當前包下進行進一步掃描,此時可以看到有個aop 的子包,下面有個配置類 AopAutoConfiguration。沒錯,這就是 spring-boot 中,spring-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 {

	}

}
  1. @Configuration 說明是配置類,會被spring掃描到
  2. @ConditionalOnClass 即當前classpath下面,有這幾個類EnableAspectJAutoProxyAspectAdviceAnnotatedElement 纔回去加載該類,通俗說就是 即有spring-aop 依賴纔會加載。
  3. @ConditionalOnProperty 在上一步,再一步對配置進行條件判斷,即判斷是否有spring.aop.auto=true 則加載。matchIfMissing = true 或者沒有該配置,則默認加載配置。
    類上註解分析完,下面看內部類註解:
  4. spring 代理方式有兩種,一種是jdk代理(需要有接口方式進行代理),一種是cglib方式(不需要接口,以子類方式,但是無法代理final方法)。如上面配置,默認下是使用 cglib進行代理。

下面看兩個子類都有的註解 @EnableAspectJAutoProxy

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	boolean proxyTargetClass() default false;
	boolean exposeProxy() default false;

}

除了兩個屬性外,還引入了一個 AspectJAutoProxyRegistrarAspectJAutoProxyRegistrar 則爲一個 ImportBeanDefinitionRegistrar,它將重寫 registerBeanDefinitions 來註冊自己的bean。

	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
			// 註冊 AnnotationAwareAspectJAutoProxyCreator
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
		// 設置 EnableAspectJAutoProxy 來的兩個屬性 proxyTargetClass 和 exposeProxy 到 AnnotationAwareAspectJAutoProxyCreator 中
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
  1. 註冊 AnnotationAwareAspectJAutoProxyCreator,這是spring-aop的核心入口類。
  2. 設置 EnableAspectJAutoProxy 來的兩個屬性 proxyTargetClassexposeProxyAnnotationAwareAspectJAutoProxyCreator 中。

AnnotationAwareAspectJAutoProxyCreator

在這裏插入圖片描述
排除衆多類結構,發現 AnnotationAwareAspectJAutoProxyCreator 是一個 SmartInstantiationAwareBeanPostProcessor,和解析@Autowired 的類實現同一個接口,大概能猜到,在spring 容器初始化bean時候,對對應類進行代理操作 。
實現 SmartInstantiationAwareBeanPostProcessor 接口,需要實現以下方法(當然全部有默認接口):

  1. Class<?> predictBeanType(Class<?> beanClass, String beanName):預測bean類型
  2. Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) 解析獲取候選構造方法
  3. Object getEarlyBeanReference(Object bean, String beanName) 獲取bean實例,主要目的是解決spring循環依賴
  4. Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) 實例前處理
  5. boolean postProcessAfterInstantiation(Object bean, String beanName) 實例後處理
  6. PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) 設置一些屬性
  7. PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) 設置一些屬性值
  8. Object postProcessBeforeInitialization(Object bean, String beanName) 實例化前處理
  9. Object postProcessAfterInitialization(Object bean, String beanName) 實例化後處理

AnnotationAwareAspectJAutoProxyCreator 主要對以下幾個方法有具體實現:

  1. predictBeanTypeAbstractAutoProxyCreator 有實現
  2. getEarlyBeanReferenceAbstractAutoProxyCreator 有實現
  3. postProcessBeforeInstantiationAbstractAutoProxyCreator 有實現
  4. postProcessAfterInitializationAbstractAutoProxyCreator 有實現

下面從spring容器執行方法先後順序,結合例子具體分析spring-aop 原理。

postProcessBeforeInstantiation

在實例化前進行調用:

	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
	// 獲取即將緩存名字,有beanName,則返回beanName,如果爲FactoryBean類型,則加上FactoryBean&前綴;沒有beanName,則直接返回beanClass
		Object cacheKey = getCacheKey(beanClass, beanName);
		// 如果沒有beanName,或者不在 targetSourcedBeans中
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
			// 如果已包含該key,則說明已經處理過了
				return null;
			}
			// 如果該bean是spring-aop的框架內部bean,即 Advice,Pointcut,Advisor,AopInfrastructureBean 幾種bean。或者有@Aspect註解,或者,這個bean類,本身就是aspectj創建。 則加入到advisedBeans bean 並跳過。
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}
  1. 獲取即將緩存名字,有beanName,則返回beanName,如果爲FactoryBean類型,則加上FactoryBean&前綴;沒有beanName,則直接返回beanClass。
  2. 對bean進行處理,判斷是否需要跳過。isInfrastructureClass 邏輯主要是要跳過以下幾種類型:
  • Advice,Pointcut,Advisor,AopInfrastructureBean 幾種bean類型。或者有@Aspect註解,或者,這個bean類,本身就是aspectj創建。
    shouldSkip 主要有以下幾種判斷:
  • 獲取advisor過程,這個看下一小節
  • 如果有一種類型爲 AspectJPointcutAdvisor 則直接跳過
  • 執行父類的 shouldSkip 方法,父類主要是 判斷 跳過 original instance 類型bean
  1. 如果有配置 targetSource,則調用 getAdvicesAndAdvisorsForBean 獲取代理接口,並調用創建代理類接口。

findCandidateAdvisors

findCandidateAdvisors 是獲取Advisor 過程:
AnnotationAwareAspectJAutoProxyCreatorfindCandidateAdvisors方法:

	@Override
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

看父類的 AbstractAdvisorAutoProxyCreator 中方法:

	protected List<Advisor> findCandidateAdvisors() {
		Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}

具體使用 BeanFactoryAdvisorRetrievalHelperfindAdvisorBeans,這個方法主要目的是找到所有 資格的 Advisor bean類,該方法會忽略 FactoryBean 類型,以及排除 正在創建的bean。

	public List<Advisor> findAdvisorBeans() {
		// Determine list of advisor bean names, if not cached already.
		String[] advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the auto-proxy creator apply to them!
			// 直接從beanFactory中獲取所有Advisor類。
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
		if (advisorNames.length == 0) {
			return new ArrayList<>();
		}

		List<Advisor> advisors = new ArrayList<>();
		for (String name : advisorNames) {
			if (isEligibleBean(name)) {
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					if (logger.isTraceEnabled()) {
						logger.trace("Skipping currently created advisor '" + name + "'");
					}
				}
				else {
					try {
						advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
					catch (BeanCreationException ex) {
						Throwable rootCause = ex.getMostSpecificCause();
						if (rootCause instanceof BeanCurrentlyInCreationException) {
							BeanCreationException bce = (BeanCreationException) rootCause;
							String bceBeanName = bce.getBeanName();
							if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
								if (logger.isTraceEnabled()) {
									logger.trace("Skipping advisor '" + name +
											"' with dependency on currently created bean: " + ex.getMessage());
								}
								// Ignore: indicates a reference back to the bean we're trying to advise.
								// We want to find advisors other than the currently created bean itself.
								continue;
							}
						}
						throw ex;
					}
				}
			}
		}
		return advisors;
	}

在Spring中,也可以直接使用@Aspect註解,當從 findAdvisorBeans 沒有獲取到信息是,會嘗試調用 BeanFactoryAspectJAdvisorsBuilderbuildAspectJAdvisors() 獲取註解。

	public List<Advisor> buildAspectJAdvisors() {
	// 讀取緩存
		List<String> aspectNames = this.aspectBeanNames;
		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					// 獲取所有實例,即Object子類。
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
						if (!isEligibleBean(beanName)) {
						// 判斷是否已經制定表達式過濾
							continue;
						}
						// We must be careful not to instantiate beans eagerly as in this case they
						// would be cached by the Spring container but would not have been weaved.
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						if (this.advisorFactory.isAspect(beanType)) {
						// 如果是 @Aspect註解且不是aspectj動態產生的。那額
							aspectNames.add(beanName);
							// 構造 Aspect 元數據
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							// 如果改AspectJ 註解 是單例模型
							// 構造一個 BeanFactoryAspectInstanceFactory
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								// 獲取在Advice 中配置的Advisor,即PointCut信息。
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
								// 單例
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
								// 非單例
									this.aspectFactoryCache.put(beanName, factory);
								}
								advisors.addAll(classAdvisors);
							}
							else {
								// 非單例模型
								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);
										// 構造MetadataAwareAspectInstanceFactory  並緩存
								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 ArrayList<>();
		// 從獲取到的有Aspecj 註解的類,進行獲取其 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);
				// 構造 MetadataAwareAspectInstanceFactory  並加入
				advisors.addAll(this.advisorFactory.getAdvisors(factory));
			}
		}
		return advisors;
	}

整個 findCandidateAdvisors 方法有點長,但是代碼邏輯還是挺容易理解的

  1. 調用父類方法 findCandidateAdvisors 獲取 Advisor 類型類,即實現了 Advisor 接口類。AdvisorAdvice的一個點,實際上爲 Advice 的一個切點(JoinPoint)。這個接口一般不建議給Spring 使用者用,而提供給Spring 所需要的的維護者使用。
  2. 再從 BeanFactoryAspectJAdvisorsBuilderbuildAspectJAdvisors 中,將所有切面 @Advice 從beanFactory解析出,並且分別解析其PointCut,每個攔截方法,使用 Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 註解,就是一個 Advisor

this.advisorFactory.getAdvisors(factory)

往下看 this.advisorFactory.getAdvisors(factory) 具體內容:

	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
	// 獲取目標代理類
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		// 獲取切面名字
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		validate(aspectClass);

		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
		// so that it will only instantiate once.
		// 判斷是否爲懶加載切面
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
		for (Method method : getAdvisorMethods(aspectClass)) {
		// 獲取該切面類的切點信息
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// Find introduction fields.
		// 對 @DeclareParent 註解進行處理
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

上面代碼中,看對普通增強器獲取,主要方法爲: getAdvisor:

	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {
		// 驗證
		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
		// 獲取切點
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}
		// 包裝一層 InstantiationModelAwarePointcutAdvisorImpl
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

其實對於普通使用 @Aspectj 切面的處理,就是將其切點信息PointCut 獲取出來並處理:

	@Nullable
	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
	// 獲取Pointcut, Around, Before, After, AfterReturning, AfterThrowing
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}
		// 設置poincut信息後取出。
		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
		if (this.beanFactory != null) {
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
	}

上面代碼片段中,對每個方法進行獲取增強器操作,而後封裝爲 InstantiationModelAwarePointcutAdvisorImpl 返回。
InstantiationModelAwarePointcutAdvisorImpl 的構造方法,則是普通信息的填充,而主要是其內部的 instantiateAdvice ,對信息進行初始化過程。

	private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
		Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
		return (advice != null ? advice : EMPTY_ADVICE);
	}

再看 ReflectiveAspectJAdvisorFacotorygetAdvice 方法:

	@Override
	@Nullable
	public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
		// 切面類
		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);
		// 獲取方法上面註解
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		// If we get here, we know we have an AspectJ method.
		// Check that it's an AspectJ-annotated class
		if (!isAspect(candidateAspectClass)) {
			throw new AopConfigException("Advice must be declared inside an aspect type: " +
					"Offending method '" + candidateAdviceMethod + "' in class [" +
					candidateAspectClass.getName() + "]");
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Found AspectJ method: " + candidateAdviceMethod);
		}

		AbstractAspectJAdvice springAdvice;

		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
			// candidateAdviceMethod 爲候選方法,expressionPointcut 爲註解上面切點信息, aspectInstanceFactory 爲
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				springAdvice = new AspectJAfterThrowingAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
					springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
				}
				break;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}

		// Now to configure the advice...
		springAdvice.setAspectName(aspectName);
		springAdvice.setDeclarationOrder(declarationOrder);
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}

根據不同類型AspectJ註解,Spring 封裝了不同類返回。
主要有以下幾種:

  • @Around: AspectJAroundAdvice
  • @Before: AspectJMethodBeforeAdvice
  • @After: AspectJAfterAdvice
  • @AfterReturning: AspectJAfterReturningAdvice
  • @AfterThrowing: AspectJAfterThrowingAdvice

小結

本文主要分析Spring AOP入口,以及postProcessBeforeInstantiation 部分內容,下文將針對 具體 createProxy 具體分析

覺得博主寫的有用,不妨關注博主公衆號: 六點A君。
哈哈哈,一起研究Spring:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章