Spring源碼之AOP源碼解析

前言

上一篇看了Spring IOC源碼,猿猿們都知道,有IOC就有AOP,那這篇就結合例子來看一下AOP的源碼。

基本概念

AOP(Aspect Oriented Programming),即面向切面編程,可以說是OOP(Object Oriented Programming,面向對象編程)的補充和完善。OOP引入封裝、繼承、多態等概念來建立一種對象層次結構,用於模擬公共行爲的一個集合。不過OOP允許開發者定義縱向的關係,但並不適合定義橫向的關係,例如日誌功能。日誌代碼往往橫向地散佈在所有對象層次中,而與它對應的對象的核心功能毫無關係對於其他類型的代碼,如安全性、異常處理和透明的持續性也都是如此,這種散佈在各處的無關的代碼被稱爲橫切(cross cutting),在OOP設計中,它導致了大量代碼的重複,而不利於各個模塊的重用。

AOP技術恰恰相反,它利用一種稱爲"橫切"的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行爲封裝到一個可重用模塊,並將其命名爲"Aspect",即切面。所謂"切面",簡單說就是那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任封裝起來,便於減少系統的重複代碼,降低模塊之間的耦合度,並有利於未來的可操作性和可維護性。

使用"橫切"技術,AOP把軟件系統分爲兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。橫切關注點的一個特點是,他們經常發生在覈心關注點的多處,而各處基本相似,比如權限認證、日誌、事物。AOP的作用在於分離系統中的各種關注點,將核心關注點和橫切關注點分離開來。

橫切關注點

即對哪些方法進行切入,對哪些方法進行攔截,攔截後怎麼處理,這些關注點稱之爲橫切關注點。

切面(Aspect)

把原來糅雜在業務邏輯代碼中的非業務代碼抽取出來,把功能相同的放在一個類中形成一個切面。類是對物體特徵的抽象,切面就是對橫切關注點的抽象。

連接點(JoinPoint)

需要切入的點、被攔截到的點,因爲Spring只支持方法類型的連接點,所以在Spring中連接點指的就是被攔截到的方法,實際上連接點還可以是字段或者構造器。

切入點(PointCut)

對連接點進行攔截的定義。

通知(Advice)

所謂通知指的就是指攔截到連接點之後要執行的代碼,通知分爲前置、後置、異常、最終、環繞通知五種。

目標對象(Target)

代理的目標對象。

織入(Weave)

將切面應用到目標對象並導致代理對象創建的過程。

引入(Introduction)

在不修改代碼的前提下,引入可以在運行期爲類動態地添加一些方法或字段。

基本概念網上有很多,就不細說了。這裏要提一下AOP是一種思想,它的實現主要有Spring AOP和AspectJ,Spring實現AOP的底層相當複雜,所以藉助了AspectJ的語法來實現,即使用了@Aspect註解來實現。
Spring AOP是在運行期進行織入的,而AspectJ是在編譯期進行織入。

類結構體系

在這裏插入圖片描述
在這裏插入圖片描述

示例代碼

配置類

@Configuration
@ComponentScan(value = "com.ambition")
/**
 * Spring AOP 默認使用 JDK 動態代理
 *
 * proxyTargetClass = true 時則代理目標對象時強制使用 CGLIB 代理
 * @see DefaultAopProxyFactory#createAopProxy(org.springframework.aop.framework.AdvisedSupport)
 *
 * exposeProxy = true 暴露代理對象,這樣就可以使用 AopContext.currentProxy() 方法獲取當前代理的對象
 * @see AopContext#currentProxy
 * @see JdkDynamicAopProxy#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
 *
 * 可以解決在方法裏面調方法,或者用 this 關鍵字調方法,而無法被代理的情況
 **/
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class AopConfig {

}

切面類

@Aspect
@Component
public class AmbitionAop {

	@Pointcut("execution(* com.ambition.service.CalculateImpl.*(..))")
	public void pointCut() { }

	@Before(value = "pointCut()")
	public void methodBefore(JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		System.out.println("執行目標方法【" + methodName + "】之前執行<前置通知>, 入參" + Arrays.asList(joinPoint.getArgs()));
	}

	@After(value = "pointCut()")
	public void methodAfter(JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		System.out.println("執行目標方法【" + methodName + "】之前執行<後置通知>, 入參" + Arrays.asList(joinPoint.getArgs()));
	}

	@AfterReturning(value = "pointCut()")
	public void methodReturning(JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		System.out.println("執行目標方法【" + methodName + "】之前執行<返回通知>, 入參" + Arrays.asList(joinPoint.getArgs()));
	}

	@AfterThrowing(value = "pointCut()")
	public void methodAfterThrowing(JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		System.out.println("執行目標方法【" + methodName + "】之前執行<異常通知>, 入參" + Arrays.asList(joinPoint.getArgs()));
	}

}

目標對象

@Component
public class CalculateImpl implements Calculate {

	@Override
	public int add(int numA, int numB) {
		// System.out.println(1 / 0);
		return numA + numB;
	}

	@Override
	public int reduce(int numA, int numB) {
		return numA - numB;
	}

	@Override
	public int div(int numA, int numB) {
		return numA / numB;
	}

	@Override
	public int multi(int numA, int numB) {
		return numA * numB;
	}

}

測試類

public static void main(String[] args) {

	AnnotationConfigApplicationContext context =
			new AnnotationConfigApplicationContext(AopConfig.class);

	Calculate calculate = context.getBean(Calculate.class);

	int result = calculate.add(1, 2);
	System.out.println("運算結果:" + result);
}

沒有異常時的打印結果
在這裏插入圖片描述
發生異常時的打印結果
在這裏插入圖片描述

產生過程

先來看一下它是如何被Spring IOC容器初始化並生成代理對象的,順便說一下上一篇沒有具體說明的部分,再說它的執行過程。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	boolean proxyTargetClass() default false;

	boolean exposeProxy() default false;

}

可以看到這個註解上面導入了一個AspectJAutoProxyRegistrar類,它實現了ImportBeanDefinitionRegistrar,解析IOC源碼的時候,我們看到Spring會將這種類型的組件放到一個集合中,然後統一調用registerBeanDefinitions()方法,委託其進行BeanDefinition的註冊。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
										BeanDefinitionRegistry registry) {
		// 註冊 AspectJ 相關的處理組件
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

}

可以看到主要代碼就是AopConfigUtilsregisterAspectJAnnotationAutoProxyCreatorIfNecessary()方法。

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
	return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
																					  @Nullable Object source) {

	return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls,
															  BeanDefinitionRegistry registry,
															  @Nullable Object source) {

    // 容器中已經包含 "org.springframework.aop.config.internalAutoProxyCreator"
	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		// 獲取 BeanDefinition
		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;
	}

	/**
	 * 封裝 AnnotationAwareAspectJAutoProxyCreator 爲 RootBeanDefinition
	 *
	 * 名稱爲{@link AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME}
	 **/
	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;
}

在這裏插入圖片描述這裏Spring容器已經解析到剛剛導入的類了,然後會調用上面那個方法進行註冊。
在這裏插入圖片描述其實就是往Spring容器中註冊一個AnnotationAwareAspectJAutoProxyCreator組件,很多EnableXXX註解都是這樣將需要的組件註冊到IOC容器,然後委託初始化過程來實現功能的擴展。

protected Object createBean(String beanName,
							RootBeanDefinition mbd,
							@Nullable Object[] args) throws BeanCreationException {
	
	RootBeanDefinition mbdToUse = mbd;

	......

	try {
		/**
		 * Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		 * 給 BeanPostProcessors 一個返回代理而不是目標 Bean 實例的機會【重要】
		 * 但此時還沒有創建代理對象,此時沒有對象,只有 BeanDefinition
		 *
		 * 第一次調用後置處理器【跟 AOP 有關】
		 * @see org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization(java.lang.Object, java.lang.String)
		 *
		 * InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
		 * Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
		 *
		 * 此時對象還沒有實例化,只有 BeanDefinition
		 * 無法進行代理,只是將切面找出來進行緩存
		 */
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}

	try {
		/**
		 * 實例化 Bean
		 **/
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}

然後來看看Spring是怎麼將代理對象創建出來的,之前說resolveBeforeInstantiation()方法將切面找出來進行緩存,那麼是怎麼緩存的呢,方法跟進去看一下。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {

	Object bean = null;

	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) {
				
				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				if (bean != null) {
					
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
		}

		mbd.beforeInstantiationResolved = (bean != null);
	}

	return bean;
}

這裏第一次調用InstantiationAwareBeanPostProcessor類型的後置處理器的postProcessBeforeInstantiation()方法,第二次調用BeanPostProcessor類型的後置處理器的postProcessAfterInitialization()方法,一般只會調用第一個方法。
從上面的類體系結構圖中可以看到,AbstractAutoProxyCreatorInstantiationAwareBeanPostProcessor的子類,所以會調用它重寫的postProcessBeforeInstantiation()方法。

先說一下AbstractAdvisorAutoProxyCreator繼承了AbstractAutoProxyCreator,而它又實現了BeanFactoryAware,IOC容器在初始化過程中會回調setBeanFactory()方法,AbstractAdvisorAutoProxyCreator有一個BeanFactoryAdvisorRetrievalHelper屬性,在Spring回調的時候,會實例化爲BeanFactoryAdvisorRetrievalHelperAdapter,它繼承了BeanFactoryAdvisorRetrievalHelper,這個類在後面會有很大用處。
AnnotationAwareAspectJAutoProxyCreator繼承了AspectJAwareAdvisorAutoProxyCreator,它在Spring回調的時候,實例化了一個ReflectiveAspectJAdvisorFactory類,它繼承了AbstractAspectJAdvisorFactory,它又實現了AspectJAdvisorFactory,和另一個BeanFactoryAspectJAdvisorsBuilderAdapter類,
它繼承了BeanFactoryAspectJAdvisorsBuilder
不用委託Spring注入,回調的時候進行實例化,Get了一項新技能,就是費頭髮。
看圖更清晰一點:
在這裏插入圖片描述

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
	Object cacheKey = getCacheKey(beanClass, beanName);
	
	if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
		// 已經被代理過則返回
		if (this.advisedBeans.containsKey(cacheKey)) {
			return null;
		}
		// 不應代理 或者 應該跳過
		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return null;
		}
	}

	TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
	if (targetSource != null) {
		if (StringUtils.hasLength(beanName)) {
			this.targetSourcedBeans.add(beanName);
		}
		// 獲取所有合格的增強器
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
		// 創建 AOP 代理
		Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
		// 存入緩存
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}

	return null;
}

這裏shouldSkip()方法就是緩存切面通知的地方。

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
	// 查找所有候選的通知
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	
	for (Advisor advisor : candidateAdvisors) {
		/**
		 * 是 AspectJPointcutAdvisor 的子類 並且 切面名稱是 beanName
		 *
		 * 一般是 InstantiationModelAwarePointcutAdvisorImpl
		 **/
		if (advisor instanceof AspectJPointcutAdvisor &&
				((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
			return true;
		}
	}
	
	return super.shouldSkip(beanClass, beanName);
}

protected List<Advisor> findCandidateAdvisors() {
	// 之前回調的時候實例化的 BeanFactoryAdvisorRetrievalHelperAdapter
	this.advisorRetrievalHelper.findAdvisorBeans();
}

主要的方法就是findCandidateAdvisors()方法,查找所有候選的通知。這裏會先走父類的查找方法,再走子類的查找方法,主要是子類的方法。

protected List<Advisor> findCandidateAdvisors() {
	/**
	 * 添加根據超類規則找到的所有 Spring Advisors
	 *
	 * 查找要在自動代理中使用的所有候選 Advisor【找 Spring AOP 的 Advisor】
	 **/
	List<Advisor> advisors = super.findCandidateAdvisors();
	/**
	 * 構建 BeanFactory 中所有 AspectJ 方面的 Advisors
	 **/
	if (this.aspectJAdvisorsBuilder != null) {
		/**
		 * 查找帶有 AspectJ 註解的 Aspect bean【不同的註解對應不同的切面類】【找 AspectJ 的 Advisor】
		 *
		 * aspectJAdvisorsBuilder 是之前回調的時候實例化的 BeanFactoryAspectJAdvisorsBuilderAdapter
		 **/
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	}

	return advisors;
}

用之前Spring回調時初始化的BeanFactoryAspectJAdvisorsBuilderAdapter組件來構建 AspectJ 的通知。代碼如下:

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<>();

				// 獲取容器中所有組件的 beanName
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);

				for (String beanName : beanNames) {
					// 不合格則跳過
					if (!isEligibleBean(beanName)) {
						continue;
					}

					Class<?> beanType = this.beanFactory.getType(beanName);
					if (beanType == null) {
						continue;
					}
					// 是切面【具有 @Aspect 註解並且不是由 ajc 編譯】
					if (this.advisorFactory.isAspect(beanType)) {
						aspectNames.add(beanName);
						AspectMetadata amd = new AspectMetadata(beanType, beanName);
						// AspectJ支持的不同子句(切面實例化模型)是單例的
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							MetadataAwareAspectInstanceFactory factory =
									new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
							/**
							 * 獲取 AspectJ 註解對應的切面增強處理類
							 **/
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							// 是單例則存入 Map<String, List<Advisor>> 緩存
							if (this.beanFactory.isSingleton(beanName)) {
								this.advisorsCache.put(beanName, classAdvisors);
							}
							// 否則存入 Map<String, MetadataAwareAspectInstanceFactory> 緩存
							else {
								this.aspectFactoryCache.put(beanName, factory);
							}

							advisors.addAll(classAdvisors);
						}
						else {
							if (this.beanFactory.isSingleton(beanName)) {
								throw new IllegalArgumentException();
							}
							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 ArrayList<>();
	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;
}

主要方法就是ReflectiveAspectJAdvisorFactorygetAdvisors()方法。代碼如下:

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
	// 獲取切面類
	Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
	// 獲取切面類名稱
	String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
	// 校驗
	validate(aspectClass);

	/**
	 * 用裝飾器包裝 MetadataAwareAspectInstanceFactory,使其僅實例化一次
	 **/
	MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
			new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

	List<Advisor> advisors = new ArrayList<>();
	// 遍歷所有的除標註 @Pointcut 註解的通知方法
	for (Method method : getAdvisorMethods(aspectClass)) {
		// 獲取對應的增強器
		Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
		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;
	}
	// 獲取對應的增強器【重要】
	return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
			this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
												  Method aspectJAdviceMethod,
												  AspectJAdvisorFactory aspectJAdvisorFactory,
												  MetadataAwareAspectInstanceFactory aspectInstanceFactory,
												  int declarationOrder,
												  String aspectName) {

	this.declaredPointcut = declaredPointcut;
	this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
	this.methodName = aspectJAdviceMethod.getName();
	this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
	this.aspectJAdviceMethod = aspectJAdviceMethod;
	this.aspectJAdvisorFactory = aspectJAdvisorFactory;
	this.aspectInstanceFactory = aspectInstanceFactory;
	this.declarationOrder = declarationOrder;
	this.aspectName = aspectName;
	// 惰性實例化
	if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
		Pointcut preInstantiationPointcut = Pointcuts.union(
				aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
		this.pointcut = new PerTargetInstantiationModelPointcut(
				this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
		this.lazy = true;
	}
	else {
		this.pointcut = this.declaredPointcut;
		this.lazy = false;
		// 實例化對相應的增強器
		this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
	}
}
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);
}

這裏調用的是ReflectiveAspectJAdvisorFactorygetAdvice()方法,主要就是由切面註解實例化不同的通知類。

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;
	}
	
	......

	AbstractAspectJAdvice springAdvice;
	// 由註解類型實例化不同的增強器
	switch (aspectJAnnotation.getAnnotationType()) {
		case AtPointcut:
			if (logger.isDebugEnabled()) {
				logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
			}
			return null;
		// @Around
		case AtAround:
			springAdvice = new AspectJAroundAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			break;
		// @Before
		case AtBefore:
			springAdvice = new AspectJMethodBeforeAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			break;
		// @After
		case AtAfter:
			springAdvice = new AspectJAfterAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			break;
		// @AfterReturning
		case AtAfterReturning:
			springAdvice = new AspectJAfterReturningAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
			if (StringUtils.hasText(afterReturningAnnotation.returning())) {
				springAdvice.setReturningName(afterReturningAnnotation.returning());
			}
			break;
		// @AfterThrowing
		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();
	}

	// 配置屬性
	springAdvice.setAspectName(aspectName);
	springAdvice.setDeclarationOrder(declarationOrder);
	String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
	if (argNames != null) {
		springAdvice.setArgumentNamesFromStringArray(argNames);
	}
	// 綁定參數
	springAdvice.calculateArgumentBindings();

	return springAdvice;
}

在這裏插入圖片描述這個方法執行完,可以看到將帶有切面註解的方法都轉換爲對應的通知方法了。

創建過程

那麼前期的準備工作就執行完了,創建工作從AbstractAutowireCapableBeanFactoryinitializeBean()開始。

protected Object initializeBean(final String beanName,
								final Object bean,
								@Nullable RootBeanDefinition mbd) {
	// 回調 Aware 及其實現類的方法
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged(
				(PrivilegedAction<Object>) () -> {
					invokeAwareMethods(beanName, bean);
					return null;
				},
				getAccessControlContext());
	}
	else {
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		/**
		 * 關鍵字:執行
		 * 執行 BeanPostProcessor 直接實現類的 postProcessBeforeInitialization() 方法
		 *
		 * @PostConstruct 註解是在這裏面進行處理的
		 */
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		/**
		 * 執行 Bean 生命週期回調中的 init 方法
		 *
		 * 實現 InitializingBean 接口並重寫 afterPropertiesSet() 方法是在這裏面進行處理的
		 */
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
		/**
		 * 關鍵字:改變
		 * 執行 BeanPostProcessor 直接實現類的 postProcessAfterInitialization() 方法
		 *
		 * 產生 AOP 代理,事務的代理等
		 */
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

applyBeanPostProcessorsAfterInitialization()方法跟進去,發現其調用了BeanPostProcessor類型的後置處理器的postProcessAfterInitialization()方法,這裏就會進到AbstractAutoProxyCreatorpostProcessAfterInitialization()方法。

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			// 如果需要則進行包裝
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

主要代碼就是wrapIfNecessary()方法了,跟進去:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	// 沒有代理過
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	// 是不應代理的基礎結構類 或者 需要跳過
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	/**
	 * 獲取所有合格的增強器
	 *
	 * 通過註解方式和 XML【<aop:advisor>】 方式配置的增強器
	 **/
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, 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;
	}

	// 否則標記爲未代理
	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}

getAdvicesAndAdvisorsForBean()方法,有一部分代碼跟之前的一樣,主要多了查找可以應用於指定Bean的增強器這一過程,就不細說了,主要說createProxy()創建代理對象方法:

protected Object createProxy(Class<?> beanClass,
							 @Nullable String beanName,
							 @Nullable Object[] specificInterceptors,
							 TargetSource targetSource) {
	// beanFactory【DefaultListableBeanFactory】 是 ConfigurableListableBeanFactory 的子類
	if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
		/**
		 * 暴露目標對象
		 *
		 * 設置 originalTargetClass 屬性值爲 beanClass
		 **/
		AutoProxyUtils.exposeTargetClass(
				(ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass
		);
	}

	// 代理工廠
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);
	/**
	 * proxyTargetClass 屬性值是否爲 False,默認爲 False
	 **/
	if (!proxyFactory.isProxyTargetClass()) {
		/**
		 * 確定是否應使用給定的 Bean 替代其目標類而不是其接口
		 *
		 * preserveTargetClass 屬性值爲 True
		 **/
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}

	// 構建增強器
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	// 空方法
	customizeProxyFactory(proxyFactory);

	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}
	// 獲取代理對象【重要】
	return proxyFactory.getProxy(getProxyClassLoader());
}

跟進去,最後執行的是DefaultAopProxyFactorycreateAopProxy方法:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	// 需要優化【默認爲False】 或者 proxyTargetClass屬性值爲True【默認爲False】 或者 沒有用戶提供的代理接口
	if (config.isOptimize() || config.isProxyTargetClass()
			|| hasNoUserSuppliedProxyInterfaces(config)) {
		// 目標類
		Class<?> targetClass = config.getTargetClass();
		if (targetClass == null) {
			throw new AopConfigException();
		}
		// 是接口 或者 是代理的類
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			// 使用 JDK 動態代理
			return new JdkDynamicAopProxy(config);
		}
		// 使用 CGLIB 代理
		return new ObjenesisCglibAopProxy(config);
	}
	// 默認使用 JDK 動態代理
	else {
		return new JdkDynamicAopProxy(config);
	}
}

這裏實例化代理對象的時候,傳了一個AdvisedSupport參數,後面調用的時候轉換爲攔截器會用到它的方法。
傳入後置處理器邏輯執行完之後,就可以看到創建的代理對象被織入了切面信息,感覺就像一個尋寶的過程,猿猿的生活就是這麼樸實無華且枯燥。
在這裏插入圖片描述

執行過程

因爲目標對象是一個JDK代理對象,所以執行目標方法會被上面實例化的JdkDynamicAopProxy代理對象的invoke()方法攔截:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	MethodInvocation invocation;
	Object oldProxy = null;
	boolean setProxyContext = false;

	TargetSource targetSource = this.advised.targetSource;
	Object target = null;

	try {
		// 代理接口沒有定義 equals 方法 且 調用的是目標對象的 equals 方法
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			// 目標對象沒有自己實現 equals 方法
			return equals(args[0]);
		}
		// 代理接口沒有定義 hashCode 方法 且 調用的是目標對象的 hashCode 方法
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			// 目標對象沒有自己實現 hashCode 方法
			return hashCode();
		}
		// 聲明類型是 DecoratingProxy
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		// 透明 且 聲明類型是個接口 且 聲明類型是 Advised
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface()
				&& method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		Object retVal;
		/**
		 * 如果設置了 exposeProxy = true 則將代理對象設置到線程本地變量中
		 *
		 * @see org.springframework.context.annotation.EnableAspectJAutoProxy#exposeProxy()
		 **/
		if (this.advised.exposeProxy) {
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);

		/**
		 * 獲取此方法的攔截鏈
		 **/
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		/**
		 * 檢查是否有其他通知
		 * 如果沒有,可以依靠目標直接反射調用,並避免創建 MethodInvocation
		 **/
		if (chain.isEmpty()) {
			/**
			 * 我們可以跳過創建 MethodInvocation 的操作:僅直接調用目標
			 * 請注意,最終的調用者必須是 InvokerInterceptor
			 **/
			// 使給定參數適應給定方法中的目標籤名
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			// 通過反射調用給定目標
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			/**
			 * 創建一個 ReflectiveMethodInvocation
			 **/
			invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			/**
			 * 通過攔截器鏈進入連接點【責任鏈模式】
			 **/
			retVal = invocation.proceed();
		}

		Class<?> returnType = method.getReturnType();
		if (retVal != null && retVal == target && returnType != Object.class
				&& returnType.isInstance(proxy)
				&& !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
			retVal = proxy;
		}
		else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
			throw new AopInvocationException();
		}

		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

現在我們已經將通知織入到目標方法中去了,但是是如何執行這些通知方法的呢,getInterceptorsAndDynamicInterceptionAdvice()方法看一下:

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, 
																@Nullable Class<?> targetClass) {
												
	// 目標對象方法的緩存鍵
	// public abstract int com.ambition.service.Calculate.add(int,int)					
	MethodCacheKey cacheKey = new MethodCacheKey(method);
	// 先去緩存中獲取
	List<Object> cached = this.methodCache.get(cacheKey);
	if (cached == null) {
		// 緩存中沒有,則進行邏輯解析
		cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
				this, method, targetClass);
		// 放入緩存中
		this.methodCache.put(cacheKey, cached);
	}

	return cached;
}

Spring的設計思路很多操作都是先去緩存中獲取,獲取不到再進行復雜耗時的邏輯解析,然後放入緩存中,下次就直接獲取到了,優化了性能,敲黑板。
AdvisedSupport類有一個AdvisorChainFactory屬性,實例化了DefaultAdvisorChainFactory,由它進行邏輯解析。

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config,
																Method method,
																@Nullable Class<?> targetClass) {

	// 獲取 DefaultAdvisorAdapterRegistry 實例
	AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
	// 獲取通知
	Advisor[] advisors = config.getAdvisors();
	// 攔截器集合
	List<Object> interceptorList = new ArrayList<>(advisors.length);
	// 目標類
	Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());

	Boolean hasIntroductions = null;

	for (Advisor advisor : advisors) {
		// 是 PointcutAdvisor 切點通知類型,DefaultPointcutAdvisor 和 InstantiationModelAwarePointcutAdvisorImpl 都符合條件
		if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
			// 代理配置以預先過【默認爲False】 或者 切面與目標類匹配
			if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
				// 獲取 TrueMethodMatcher 或 AspectJExpressionPointcut 方法匹配器
				MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
				boolean match;
				// TrueMethodMatcher 不是 IntroductionAwareMethodMatcher 的子類,AspectJExpressionPointcut 是
				if (mm instanceof IntroductionAwareMethodMatcher) {
					if (hasIntroductions == null) {
						hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
					}
					match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
				}
				else {
					match = mm.matches(method, actualClass);
				}

				// 匹配
				if (match) {
					// 轉換爲攔截器
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					if (mm.isRuntime()) {
						for (MethodInterceptor interceptor : interceptors) {
							// 封裝爲 InterceptorAndDynamicMethodMatcher
							interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
						}
					}
					else {
						interceptorList.addAll(Arrays.asList(interceptors));
					}
				}
			}
		}
		// 是 IntroductionAdvisor 類型
		else if (advisor instanceof IntroductionAdvisor) {
			IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
			if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}
		else {
			Interceptor[] interceptors = registry.getInterceptors(advisor);
			interceptorList.addAll(Arrays.asList(interceptors));
		}
	}

	return interceptorList;
}

主要功能就是將通知類轉換爲攔截器類,執行完後可以看到AspectJAfterReturningAdvice轉換爲了AfterReturningAdviceInterceptorAspectJMethodBeforeAdvice轉換爲了MethodBeforeAdviceInterceptorAspectJAfterAdviceAspectJAroundAdviceAspectJAfterThrowingAdvice本身就是攔截器。
在這裏插入圖片描述
如果沒有攔截器,則直接反射調用目標方法。有的話則封裝爲ReflectiveMethodInvocation對象,調用它的proceed()方法進行攔截處理。

public Object proceed() throws Throwable {
	/**
	 * 從索引 -1 開始並提前增加【通過遞歸調用】
	 * 確保所有的責任者都完成處理邏輯
	 **/
	// 是最後一個攔截器
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		// 直接通過反射調用目標方法
		return invokeJoinpoint();
	}

	/**
	* 獲取下一個責任者
	 *
	 * ExposeInvocationInterceptor
	 * AspectJAfterThrowingAdvice
	 * AfterReturningAdviceInterceptor
	 * AspectJAfterAdvice
	 * AspectJAroundAdvice
	 * MethodBeforeAdviceInterceptor
	 **/
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	/**
	 * 是 InterceptorAndDynamicMethodMatcher 類型
	 * 這裏都不是這個類型
	 **/
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
		if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			/**
			 * 動態匹配失敗,跳過此攔截器並調用鏈中的下一個攔截器
			 **/
			return proceed();
		}
	}
	else {
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

這裏的設計使用了一個currentInterceptorIndex從 -1 開始的索引下標,通過遞歸調用,如果是最後一個攔截器,則直接反射調用目標方法,如果不是,則獲取下一個攔截器,很巧妙,給大佬Orz了。

最後看一下各個攔截器的調用方法。
ExposeInvocationInterceptorinvoke()方法:

public Object invoke(MethodInvocation mi) throws Throwable {
	MethodInvocation oldInvocation = invocation.get();
	invocation.set(mi);
	try {
		// 返回
		return mi.proceed();
	}
	finally {
		invocation.set(oldInvocation);
	}
}

主要是用ThreadLocal將當前MethodInterceptor進行暴露。
AspectJAfterThrowingAdviceinvoke()方法:

public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		// 返回
		return mi.proceed();
	}
	catch (Throwable ex) {
		// 拋異常則調用
		if (shouldInvokeOnThrowing(ex)) {
			invokeAdviceMethod(getJoinPointMatch(), null, ex);
		}
		throw ex;
	}
}

這個攔截器主要是處理異常的,有異常就做事,沒有異常就什麼也不幹。之後的調用處理拋了異常,都會被這裏捕獲。
AfterReturningAdviceInterceptorinvoke()方法:

public Object invoke(MethodInvocation mi) throws Throwable {
	Object retVal = mi.proceed();
	// 如果發生異常,則返回通知不執行,返回到異常通知邏輯,被捕獲
	this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
	return retVal;
}

AspectJAfterAdviceinvoke()方法:

public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		// 返回
		return mi.proceed();
	}
	finally {
		// 返回通知一定會執行是因爲放在 finally 塊中
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}
}

AspectJAroundAdviceinvoke()方法:

public Object invoke(MethodInvocation mi) throws Throwable {
	// ReflectiveMethodInvocation 是 ProxyMethodInvocation
	if (!(mi instanceof ProxyMethodInvocation)) {
		throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
	}
	ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
	ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
	JoinPointMatch jpm = getJoinPointMatch(pmi);
	// 調用環繞通知方法
	return invokeAdviceMethod(pjp, jpm, null, null);
}
protected Object invokeAdviceMethod(@Nullable JoinPointMatch jpMatch,
										@Nullable Object returnValue,
										@Nullable Throwable ex) throws Throwable {
	// 用給定的參數調用通知方法
	return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}

protected Object invokeAdviceMethod(JoinPoint jp,
									@Nullable JoinPointMatch jpMatch,
									@Nullable Object returnValue,
									@Nullable Throwable t) throws Throwable {

	return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {

	// 處理調用參數
	Object[] actualArgs = args;
	if (this.aspectJAdviceMethod.getParameterCount() == 0) {
		actualArgs = null;
	}

	try {
		// 使給定的方法可訪問,並在必要時明確將其設置爲可訪問
		ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
		/**
		 * 反射調用增強處理方法
		 *
		 * @see AopUtils#invokeJoinpointUsingReflection(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
		 **/
		return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
	}
	catch (IllegalArgumentException ex) {
		throw new AopInvocationException();
	}
	catch (InvocationTargetException ex) {
		throw ex.getTargetException();
	}
}

MethodBeforeAdviceInterceptorinvoke()方法:

public Object invoke(MethodInvocation mi) throws Throwable {
	// 前置通知邏輯
	this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
	// 返回
	return mi.proceed();
}

所以可以看到,攔截器的執行順序是:
在這裏插入圖片描述

這就是爲什麼在沒有環繞通知的情況下,沒有異常的執行順序是先執行前置通知,再執行後置通知,最後執行返回通知。
有異常的情況下,先執行前置通知,再執行後置通知,最後執行異常通知。
並且後置通知只要有就一定會執行。

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