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)

所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五种。

扫描二维码关注公众号,回复: 11256880 查看本文章

目标对象(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();
}

所以可以看到,拦截器的执行顺序是:
在这里插入图片描述

这就是为什么在没有环绕通知的情况下,没有异常的执行顺序是先执行前置通知,再执行后置通知,最后执行返回通知。
有异常的情况下,先执行前置通知,再执行后置通知,最后执行异常通知。
并且后置通知只要有就一定会执行。

猜你喜欢

转载自blog.csdn.net/CX610602108/article/details/105904591