【源码剖析】Spring AOP 详解
在之前的博文中,本人讲解了 Spring IOC
的相关源码
并在大概一年前的博文中,也自己半实现了 AOP 的功能
但是,作为一个学生党,自己实现的肯定和 Spring AOP
大相径庭
那么,在本篇博文中,本人就来讲解下 Spring AOP
的相关源码:
首先,本人来给出一个调用了 Spring AOP
所提供的 API 的Demo:
API调用:
切面类:
package edu.youzg.aop.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAspect {
@Pointcut("execution(* edu.youzg.aop..*.*(..))")
public void anyMethod() {
}
//前置通知:在目标方法执行前执行-->目标方法的第一行
@Before("anyMethod()")
public void before(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
String mname = joinPoint.getSignature().getName();
String cname = joinPoint.getTarget().getClass().getName();
//输出什么类,什么方法,什么时间,什么参数被执行了
String msg = String.format("before====类名:[" + cname + "] 方法名:[" + mname + "] 参数:[" + args + "]==");
System.out.println(msg);
}
// <!--最终通知-->
@AfterReturning("anyMethod()")
public void returning(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
String mname = joinPoint.getSignature().getName();
String cname = joinPoint.getTarget().getClass().getName();
//输出什么类,什么方法,什么时间,什么参数被执行了
String msg = String.format("AfterReturning====类名:[" + cname + "] 方法名:[" + mname + "] 参数:[" + args + "]==");
System.out.println(msg);
}
// <!--后置通知-->
@After("anyMethod()")
public void after(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
String mname = joinPoint.getSignature().getName();
String cname = joinPoint.getTarget().getClass().getName();
//输出什么类,什么方法,什么时间,什么参数被执行了
String msg = String.format("after====类名:[" + cname + "] 方法名:[" + mname + "] 参数:[" + args + "]==");
System.out.println(msg);
}
//<!--异常通知-->
@AfterThrowing(value = "anyMethod()", throwing = "t")
public void throwing(JoinPoint joinPoint, Throwable t) {
System.out.println("=========AfterThrowing===========" + t.getMessage());
}
// <!--环绕通知-->
@Around("anyMethod()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object result = null;
System.out.println("======around方法开始执行之前");
result = pjp.proceed();
System.out.println("=======around方法开始执行完毕");
return result;
}
}
业务类:
package edu.youzg.aop.service;
import org.springframework.stereotype.Service;
/**
* @Author: Youzg
* @CreateTime: 2020-05-01 20:33
* @Description:带你深究Java的本质!
*/
@Service
public class UserServiceImpl {
public void login() {
System.out.println("service层login方法执行!");
}
public void register() {
System.out.println("service层register方法执行!");
}
public void rename() {
System.out.println("service层rename方法执行!");
}
public void cancellat() {
System.out.println("service层cancellat方法执行!");
}
}
配置类:
package edu.youzg.aop.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAspectJAutoProxy
@Configuration
@ComponentScan("edu.youzg.aop")
public class YouzgConfig {
}
测试类:
package edu.youzg.aop.demo;
/**
* @Author: Youzg
* @CreateTime: 2021-03-20 16:50
* @Description: 带你深究Java的本质!
*/
import edu.youzg.aop.config.YouzgConfig;
import edu.youzg.aop.service.UserServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author: Youzg
* @CreateTime: 2020-05-01 20:40
* @Description:带你深究Java的本质!
*/
public class YouzgTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(YouzgConfig.class);
UserServiceImpl userService = context.getBean("userServiceImpl", UserServiceImpl.class);
userService.login();
}
}
那么,本人现在来展示下 运行结果:
在 结合源码 进行讲解之前,本人先来 简要总结 下 Spring AOP
的 执行流程:
执行流程:
其实,只要我们仔细思考,都能想到:
- 筛选 Advisors
- 创建 代理对象
- 执行 代理对象 的 增强方法
现在,本人就来通过源码,来讲解下 Spring AOP
是如何 实现上述步骤的:
AOP代理构建入口:
在之前的博文《【源码剖析】Spring IOC 详解》中,本人也讲过:
Spring AOP
的 部分实现逻辑,在 AbstractAutoProxyCreator类 的 postProcessAfterInitialization()方法 中实现
因为 AOP 只有在 初始化了目标bean对象 后,才能 创建 动态代理
那么,本人再来展示下那部分源码:
那么,本人来展示下 为 bean对象,创建代理对象 的相关代码:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/*
* 如果是基础设施类(Pointcut、Advice、Advisor 等接口的实现类),或是应该跳过的类,
* 则不应该生成代理,此时直接返回 bean
*/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// 将 <cacheKey, FALSE> 键值对放入缓存中,供上面的 if 分支使用
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 为目标 bean 查找合适的通知器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
/*
* 若 specificInterceptors != null,即 specificInterceptors != DO_NOT_PROXY,
* 则为 bean 生成代理对象,否则直接返回 bean
*/
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());
/*
* 返回代理对象,此时 IOC 容器输入 bean,得到 proxy。此时,
* beanName 对应的 bean 是代理对象,而非原始的 bean
*/
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
// specificInterceptors = null,直接返回 bean
return bean;
}
构建 Advisors列表:
我们跟进去 第20行代码,看看是如何执行的:
可以看到:
这个方法的 作用 是:
获取 匹配上的通知器
那么,我们来跟进去,看看究竟是如何 获取到匹配的通知器 的:
我们跟进 上图中的76行,来看下时如何查询的:
继续跟进 94行 代码:
可以看到,使用一个 Helper
进行了封装
(我们可以理解 XxxHelper
为 操作Xxx的工具)
那么,我们继续向下跟:
筛选Advisors:
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = null;
synchronized (this) {
// cachedAdvisorBeanNames 是 advisor 名称的缓存
advisorNames = this.cachedAdvisorBeanNames;
/*
* 如果 cachedAdvisorBeanNames 为空,这里到容器中查找,
* 并设置缓存,后续直接使用缓存即可
*/
if (advisorNames == null) {
// 从容器中查找 Advisor 类型 bean 的名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// 设置缓存
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
List<Advisor> advisors = new LinkedList<Advisor>();
// 遍历 advisorNames
for (String name : advisorNames) {
if (isEligibleBean(name)) {
// 忽略正在创建中的 advisor bean
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
/*
* 调用 getBean 方法从容器中获取名称为 name 的 bean,
* 并将 bean 添加到 advisors 中
*/
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
本人来总结下 上面源码 的 作用:
- 在容器中,查找所有 类型为Advisor 的 beanName
- 遍历 advisorNames,并从容器中获取 对应的 bean实例对象
我们继续向下跟进:
继续跟进:
可以看到:
在上面的方法中,检验了每一个Advisor的 合法性
那么,我们再来看看后面的 sortAdvisors()方法:
排序各个Advisors:
我们再来跟进下 153行 代码:
我们来看看 INSTANCE 这个 排序器 的 排序规则:
可以看到:
使用了 自定义排序器 进行了 排序
而具体是按照什么顺序呢?
具体是怎么读取的,本人就不在这里展示了
同学们只要知道上述的实现步骤就可以了
那么,排序之后,整个 有序的Advisor列表 就会被返回
之后,就会执行 添加扩展Advisor 的操作:
添加扩展Advisor:
我们点进去:
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// 如果通知器列表是一个空列表,则啥都不做
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
/*
* 下面的 for 循环用于检测 advisors 列表中是否存在
* AspectJ 类型的 Advisor 或 Advice
*/
for (Advisor advisor : advisors) {
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
}
}
/*
* 向 advisors 列表的首部添加 DefaultPointcutAdvisor,
* 便于之后的操作
*/
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
private static boolean isAspectJAdvice(Advisor advisor) {
return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
advisor.getAdvice() instanceof AbstractAspectJAdvice ||
(advisor instanceof PointcutAdvisor &&
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
}
这里的代码,作用也很简单:
向 Advisor列表 的 首部 添加 DefaultPointcutAdvisor通知器
那么,上述通知器究竟有什么作用,本人将在下文进行阐述!
那么,接下来就是 创建代理对象 的操作:
创建 代理对象:
我们继续向下执行,到 AOP代理构建入口 方法 的 第35行 时,就会创建 目标bean对象 的 代理对象:
那么,我们跟进去看看是如何创建的:
参数检验,构建Advisors:
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
/*
* 默认配置下,或用户显式配置 proxy-target-class = "false" 时,
* 这里的 proxyFactory.isProxyTargetClass() 也为 false
*/
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
/*
* 检测 beanClass 是否实现了接口,若未实现,则将
* proxyFactory 的成员变量 proxyTargetClass 设为 true
*/
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// specificInterceptors 中若包含有 Advice,此处将 Advice 转为 Advisor
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());
}
我们继续跟进 上面代码中 的 最后一行代码:
创建代理对象:
我们来看看是如何创建 AOP代理对象 的:
AOP代理对象 的构建:
我们继续向下跟进:
DefaultAopProxyFactory类:
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
/*
* 条件1:config.isOptimize() - 是否需要优化
* 条件2:config.isProxyTargetClass() - 检测 proxyTargetClass 的值
* 条件3:hasNoUserSuppliedProxyInterfaces(config)
* - 目标 bean 是否实现了接口
*/
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 创建 CGLIB 代理,ObjenesisCglibAopProxy 继承自 CglibAopProxy
return new ObjenesisCglibAopProxy(config);
}
else {
// 创建 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
}
可以看到:
这个方法的作用是:
根据之前的扫描结果 和 被代理的bean
选择 创建 Cglib代理 或是 JDK动态代理
那么,最后,我们来看看 创建代理对象 的 getProxy()方法 是怎样执行的:
创建 bean的代理对象:
我们来看看其实现类:
那么,我们再来看看这两个实现类会怎么执行:
可以看到:
在上面的方法中,调用了 cglib代理方法 或 jdk动态代理方法 的 原生API,创建了 bean的代理对象
但是,在创建之后,并没有返回 原生的代理对象
而是进行了一层封装,返回了 AOP封装的代理对象,这就决定了,之后的 代理对象执行方法,也要按照 AOP的顺序 来执行
如下图:
那么,本人来通过一张 流程图,总结 下 创建代理对象 的 流程:
代理对象 创建流程:
在这里,本人先说明一点:
cglib代理,对于每一个被代理的方法,都会创建 派生类
在我们执行方法时,内部会根据一定的 路由规则,向每一个派生类 派发 任务,由它们去执行
那么,在本篇博文中,本人就以JDK动态代理的 执行流程,来讲解下 Spring AOP
的 执行增强方法 的 流程:
执行 增强方法:
首先,是 方法执行的入口:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
// 省略部分代码
Object retVal;
// 如果 expose-proxy 属性为 true,则暴露代理对象
if (this.advised.exposeProxy) {
// 向 AopContext 中设置代理对象
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 获取 拦截器链(与当前方法匹配的拦截器和通知器)
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果 拦截器链 为空,则 直接执行目标方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 通过反射执行目标方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 创建一个方法调用器,并将拦截器链传入其中
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())) {
// 如果方法返回值为 this,即 return this; 则将代理对象 proxy 赋值给 retVal
retVal = proxy;
}
// 如果返回值类型为基础类型,比如 int,long 等,当返回值为 null,抛出异常
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
经过阅读上面的源码,本人来做一下总结:
- 判断是否 暴露代理对象
- 获取 拦截器链(与当前方法匹配的拦截器和通知器)
- 若 拦截器链为空,则 直接通过反射执行目标方法
若 拦截器链不为空,则 创建方法调用 ReflectiveMethodInvocation 对象- 调用 ReflectiveMethodInvocation 对象的 proceed() 方法 ,调用 整条拦截器链
- 处理返回值,并返回该值
那么,我们先来看看 是如何 获取拦截器链 的:
获取 拦截器链:
我们继续跟下去:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
// registry 为 DefaultAdvisorAdapterRegistry 类型
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 遍历 advisor列表
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
/*
* 调用 ClassFilter 对 bean 类型进行匹配,无法匹配则说明当前通知器
* 不适合应用在当前 bean 上
*/
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 将 advisor 中的 advice 转成相应的拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
// 通过方法匹配器对目标方法进行匹配
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
// 若 isRuntime 返回 true,则表明 MethodMatcher 要在运行时做一些检测
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
// IntroductionAdvisor 类型的通知器,仅需进行类级别的匹配即可
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;
}
上面的代码看着很长,但是 核心步骤 很简单:
将 所有advisor 经过筛选校验,并 转换成相应的 interceptor
因为在 原生API调用过程中,是没有 通知器 的概念的
通知器是Spring抽象概念化出来的,其本质依然是 拦截器
就像 Spring MVC
中的每一个 mapping
,其本质都是 Servlet
(相关核心源码,本人将在之后的博文中进行讲解)
那么,现在我们来看看,Spring AOP
是如何 将每一个 advisor 转换成 interceptor 的:
advisor -> interceptor:
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
/*
* 若 advice 是 MethodInterceptor 类型的,直接添加到 interceptors 中即可
* (AspectJAfterAdvice 就实现了 MethodInterceptor 接口)
*/
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
/*
* 对于 AspectJMethodBeforeAdvice 等类型的通知,由于没有实现 MethodInterceptor 接口,
* 所以这里需要通过 适配器 进行转换
*/
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
那么,适配器是如何将 **advisor ** 转换成 interceptor 的呢?
我们继续跟下去:
我们能看到:
只是调用了 拦截器的单参构造
那么,到这里,本人就不跟下去了
我们来看看之后要执行的代码:
调用 拦截器链:
private int currentInterceptorIndex = -1;
public Object proceed() throws Throwable {
// 执行到最后一个拦截器,就执行 目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 执行 目标方法
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
/*
* 调用具有三个参数(3-args)的 matches 方法动态匹配目标方法,
* 两个参数(2-args)的 matches 方法用于 静态匹配
*/
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
// 调用拦截器逻辑
return dm.interceptor.invoke(this);
}
else {
// 如果匹配失败,则忽略当前的拦截器
return proceed();
}
}
else {
// 执行 拦截器方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
上面的代码,看似很长,其实我们自己看,本质上只是在 调用 拦截器链中的拦截器方法
在上面的代码中,我们能够看到,有一个方法被执行了很多次 —— invoke()方法:
拦截器 的 invoke:
在上面的代码中,我们也能发现:
每一个advisor,根据其类型不同,所构建的拦截器也是不同的
那么,本人来展示下每一个拦截器的 invoke()方法 的具体实现流程:
ExposeInvocationInterceptor:
我们可以看得出来,这里的 执行逻辑 为:
- 更新 ThreadLocal 的 invocation
- 继续 执行 下一个拦截器 的逻辑
AspectJAfterThrowingAdvice:
我们可以看得出来,这里的 执行逻辑 为:
- 继续 执行 下一个拦截器 的逻辑
- 出现异常,再执行 当前拦截器 的 异常处理逻辑
AfterReturningAdviceInterceptor:
我们可以看得出来,这里的 执行逻辑 为:
- 继续 执行 下一个拦截器 的逻辑
- 执行完毕后,执行 当前拦截器 的逻辑
AspectJAfterAdvice:
我们可以看得出来,这里的 执行逻辑 为:
- 继续 执行 下一个拦截器 的逻辑
- 执行完毕后,再执行 当前拦截器 的逻辑
MethodBeforeAdviceInterceptor:
我们可以看得出来,这里的 执行逻辑 为:
- 执行 当前拦截器 的逻辑
- 继续 执行 下一个拦截器的逻辑
那么,我们再来看看 目标方法 的 执行逻辑:
invokeJoinpoint()方法:
包装方法,我们继续向下跟进:
由此,我们可以看出:
当执行到 原方法(拦截器链中的最后一个方法):
执行完后,就会通过 递归调用栈,一层一层向上面的方法中,执行 之后的逻辑
那么,由上面的源码,我们也能看出,这是一种 职责链的设计模式
执行顺序:
再经过上文中,本人讲解的拦截器链的排序规则,我们可以理解 当前拦截器链 的 执行顺序 为:
参考文章:
那么,到这里,Spring AOP
的核心源码就讲解完毕了!
在之后的博文中,本人也将讲解下 Spring 事务
的 相关源码
再讲解些比较常考的面试题,Spring Framework 系列源码,就结束了!
觉得有帮助的同学,请不吝赞赞和关注哦表情ヾ(≧▽≦*)o