Spring AOP——源码分析
【阅读前提】:需了解 AOP 注解开发流程:链接
一、注解 @EnableAspectJAutoProxy
在配置类中添加注解@EnableAspectJAutoProxy,便开启了 AOP(面向切面编程) 功能。此注解也是了解 AOP 源码的入口。
@EnableAspectJAutoProxy @Configuration public class MainConfigOfAOP {
【1】@EnableAspectJAutoProxy 是什么?我们进入注解,查看其源码如下:发现调用 EnableAspectJAutoProxy 类,同时使用 @Import 注解向容器中导入 AspectJAutoProxyRegistrar 组件:作用是给容器中注册自定义的 Bean。
【2】进入 AspectJAutoProxyRegistrar 类,调用 registerBeanDefinitions 中的 register...Necessary 方法注册组件。
【3】 进入 register...Necessary 方法,通过源码分析:该方法向容器中注册一个 AnnotationAwareAspectJAutoProxyCreator (支持注解模式的面向切面自动代理创建器)组件,其名称为 internalAutoProxyCreator 。需要注意的是其注册的是一个 BeanDefinition(Bean 的定义信息,并没有实例化。后续分析时会说到) 。
二、研究 AnnotationAwareAspectJAutoProxyCreator
此自动代理创建器的内部功能,其等价于 AOP 的主要功能。 此类的继承结构如下:
我们进入自动代理的抽象父类 AbstractAutoProxyCreator 中发现,其实现了 SmartInstantiationAwareBeanPostProcessor 后置处理器(在 bean 初始化前后做一些操作,AOP 的特点)和 BeanFactoryAware 自动装配 BeanFactory。
AOP原理分析技巧:【看给容器中注册了什么组件, 这个组件什么时候工作,这个组件的功能是什么?】,研究透这些,原理也就清楚了。
我们从 AbstractAutoProxyCreator 父类向 AnnotationAwareAspectJAutoProxyCreator 子类的顺序,查看其内部关于后置处理器和自动装备的方法并加入断点:
【1】AbstractAutoProxyCreator :包含后置处理器前后的两个方法和自动装配的方法。
1 //后置处理器相关的方法1 2 @Override 3 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { 4 Object cacheKey = getCacheKey(beanClass, beanName); 5 6 if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { 7 if (this.advisedBeans.containsKey(cacheKey)) { 8 return null; 9 } 10 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { 11 this.advisedBeans.put(cacheKey, Boolean.FALSE); 12 return null; 13 } 14 } 15 16 //后置处理器相关的方法2 17 @Override 18 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { 19 if (bean != null) { 20 Object cacheKey = getCacheKey(bean.getClass(), beanName); 21 if (this.earlyProxyReferences.remove(cacheKey) != bean) { 22 return wrapIfNecessary(bean, beanName, cacheKey); 23 } 24 } 25 return bean; 26 } 27 28 //自动装备相关的方法 29 @Override 30 public void setBeanFactory(BeanFactory beanFactory) { 31 this.beanFactory = beanFactory; 32 }
【2】AbstractAdvisorAutoProxyCreator:重写了 setBeanFactory 方法。
1 //自动装备方法 2 @Override 3 public void setBeanFactory(BeanFactory beanFactory) { 4 super.setBeanFactory(beanFactory); 5 if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { 6 throw new IllegalArgumentException( 7 "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory); 8 } 9 initBeanFactory((ConfigurableListableBeanFactory) beanFactory); 10 }
【3】对 2中的 initBeanFactory 方法进行了重写。
1 @Override 2 protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { 3 super.initBeanFactory(beanFactory); 4 if (this.aspectJAdvisorFactory == null) { 5 this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory); 6 } 7 this.aspectJAdvisorsBuilder = 8 new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory); 9 }
三、Debug 测试类流程梳理
【1】创建 IOC 容器,传入主配置类 MainConfigOfAOP
【2】调用 AnnotationConfigApplicationContext 构造器:注册配置类和刷新容器(创建容器中的所有Bean,类似于初始化容器)
【3】调用 refresh 方法:主要查看 registerBeanPostProcessors(beanFactory); 方法,其作用是注册 bean 后置处理器,用方便来拦截 bean 的创建。
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { .... // 注册 bean 后置处理器,用来拦截 bean 的创建 registerBeanPostProcessors(beanFactory); .... }
【4】进入 registerBeanPostProcessors 调用的方法:先获取 IOC 容器中已经定义了的需要创建对象的所有后置处理器BeanPostProcessor(已定义:指我们在解析配置类的时候@EnableAspectJAutoProxy 会为我们注册一个 AnnotationAwareAspectJAutoProxyCreator 后置处理器的定义,包括默认的一些后置处理器的定义)例如:
上述列表中的 internalAutoProxyCreator 后置处理器,就是我们分析 @EnableAspectJAutoProxy 时注入的那个处理器。后置处理的注册分为以下三种情况:
■ 优先注册实现了 PriorityOrdered(优先级)接口的 BeanPostProcessors;
■ 其次注册实现了Ordered 接口的 BeanPostProcessors;
■ 注册所有常规 Beanpstprocessors;
internalAutoProxyCreator 后置处理器实现了 Ordered 接口。分析代码可知:【根据 bean定义名称 internalAutoProxyCreator 从 beanFactory 中获取注入的后置处理器】调用的方法 = beanFactory.getBean(ppName, BeanPostProcessor.class);
【5】进入上述所说的 beanFactory.getBean(ppName, BeanPostProcessor.class); 方法如下:因第一次进入容器,因此获取不到实例。会通过 getSingleton 方法创建 BeanPostProcessor 的实例,并保存到容器中。
【6】创建 internalAutoProxyCreator 的 AnnotationAwareAspectJAutoProxyCreator 实例。步骤如下:
【7】重点是:初始化 initializeBean 方法,查看实现的步骤如下:
1 //1、调用 invokeAwareMethods 处理Aware 接口的方法回调,beanName=internalAutoProxyCreator 实现了 BeanAware 接口 2 invokeAwareMethods(beanName, bean); 3 //2、应用后置处理器 BeforeInitialization 4 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 5 //3、执行自定义的初始化方法 6 invokeInitMethods(beanName, wrappedBean, mbd); 7 //4、执行后置处理器的 After方法 8 applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 9 10 //下面是上述方法的具体实现 11 12 //1、invokeAwareMethods 实现如下: 13 private void invokeAwareMethods(final String beanName, final Object bean) { 14 if (bean instanceof Aware) { 15 //..... 16 //实现了 BeanFactoryAware 接口,因此执行 setBeanFactory. 17 //bean==AnnotationAwareAspectJAutoProxyCreator 18 if (bean instanceof BeanFactoryAware) { 19 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); 20 } 21 } 22 } 23 24 25 //2、applyBeanPostProcessorsBeforeInitialization 实现如下: 26 @Override 27 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) 28 throws BeansException { 29 30 Object result = existingBean; 31 //获取所有的后置处理器,执行前置Before 处理器。 32 for (BeanPostProcessor processor : getBeanPostProcessors()) { 33 Object current = processor.postProcessBeforeInitialization(result, beanName); 34 if (current == null) { 35 return result; 36 } 37 result = current; 38 } 39 return result; 40 } 41 42 //3、invokeInitMethods 方法的具体实现 43 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) 44 throws Throwable { 45 46 boolean isInitializingBean = (bean instanceof InitializingBean); 47 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { 48 if (logger.isTraceEnabled()) { 49 logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); 50 } 51 if (System.getSecurityManager() != null) { 52 try { 53 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 54 ((InitializingBean) bean).afterPropertiesSet(); 55 return null; 56 }, getAccessControlContext()); 57 } 58 catch (PrivilegedActionException pae) { 59 throw pae.getException(); 60 } 61 } 62 else { 63 ((InitializingBean) bean).afterPropertiesSet(); 64 } 65 } 66 67 if (mbd != null && bean.getClass() != NullBean.class) { 68 String initMethodName = mbd.getInitMethodName(); 69 if (StringUtils.hasLength(initMethodName) && 70 !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && 71 !mbd.isExternallyManagedInitMethod(initMethodName)) { 72 invokeCustomInitMethod(beanName, bean, mbd); 73 } 74 } 75 } 76 77 //4、applyBeanPostProcessorsAfterInitialization 具体实现 78 @Override 79 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) 80 throws BeansException { 81 82 Object result = existingBean; 83 for (BeanPostProcessor processor : getBeanPostProcessors()) { 84 Object current = processor.postProcessAfterInitialization(result, beanName); 85 if (current == null) { 86 return result; 87 } 88 result = current; 89 } 90 return result; 91 }
【8】执行 Aware 初始化时,会调用 setBeanFactory 方法,我们追下去会发现调用的是 AbstractAdvisorAutoProxyCreator 的setBeanFactory 方法(就是我们分析 AnnotationAwareAspectJAutoProxyCreator 继承关系时的父类 )。
1 @Override 2 public void setBeanFactory(BeanFactory beanFactory) { 3 //调用父类的 setBeanFactory 4 super.setBeanFactory(beanFactory); 5 if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { 6 throw new IllegalArgumentException( 7 "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory); 8 } 9 //AnnotationAwareAspectJAutoProxyCreator 方法对此进行了重写 10 initBeanFactory((ConfigurableListableBeanFactory) beanFactory); 11 }
【9】进入 initBeanFactory 方法,我们知道此方法已被 AnnotationAwareAspectJAutoProxyCreator 重写:
【10】最终 BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功,将其添加到 beanFactory 中。
1 for (String ppName : orderedPostProcessorNames) { 2 //实例 pp==AnnotationAwareAspectJAutoProxyCreator 3 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); 4 //放入 ordered后置处理器集合 5 orderedPostProcessors.add(pp); 6 if (pp instanceof MergedBeanDefinitionPostProcessor) { 7 internalPostProcessors.add(pp); 8 } 9 } 10 //将处理器按优先级排序 11 sortPostProcessors(orderedPostProcessors, beanFactory); 12 //调用注册方法 13 registerBeanPostProcessors(beanFactory, orderedPostProcessors); 14 15 //上述注册方法的内部代码 16 private static void registerBeanPostProcessors( 17 ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) { 18 //将后置处理器都添加到bean工厂 19 for (BeanPostProcessor postProcessor : postProcessors) { 20 beanFactory.addBeanPostProcessor(postProcessor); 21 } 22 }
四、后置处理器创建后的操作
【1】以上是创建和注册 AnnotationAwareAspectJAutoProxyCreator 的过程。接下来就是对创建后的流程进行说明:AnnotationAwareAspectJAutoProxyCreator 是继承 InstantiationAwareBeanPostProcessor 的后置处理器:我们在上面说的 IOC 容器初始化时,会调用 refresh 方法:我们进入此方法看下,我们之前分析 registerBeanPostProcessors 方法,接下来分析 finishBeanFactoryInitialization 方法(实例所有剩余的单实例bean)完成 BeanFactory 初始化工作。
1 @Override 2 public void refresh() throws BeansException, IllegalStateException { 3 synchronized (this.startupShutdownMonitor) { 4 //...... 5 // 注册 bean后置处理器 来拦截 bean 的创建。 6 registerBeanPostProcessors(beanFactory); 7 //...... 8 // 初始化特定上下文子类中的其他特殊bean。 9 onRefresh(); 10 //...... 11 // 实例化所有剩余的(非延迟初始化)单例。 12 finishBeanFactoryInitialization(beanFactory); 13 }
【2】遍历获取容器中所有的 Bean ,依次创建对象 getBean(beanName); 流程:getBean -> doGetBean() -> getSingleton(),getBean 方法如下:先从缓存中获取当前 bean,如果能获取到说明 bean 是之前被创建过的,直接使用,否则创建bean;只要是创建好的 bean 都会被缓存起来。
1 // 先检查单例缓存中是否有已存在手动注册的单例,如果存在说明之前bean已创建 2 Object sharedInstance = getSingleton(beanName); 3 //缓存中不存在 bean 时才创建该单例 bean 4 if (sharedInstance != null && args == null) { 5 //... 6 }else{ 7 //创建bean实例。 8 if (mbd.isSingleton()) { 9 sharedInstance = getSingleton(beanName, () -> { 10 try { 11 return createBean(beanName, mbd, args); 12 } 13 catch (BeansException ex) { 14 destroySingleton(beanName); 15 throw ex; 16 } 17 }); 18 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 19 } 20 }
【2.1】进入创建 bean 的步骤: createBean 方法,首先会调用 resolveBeforeInstantiation 方法,让 beanPostProcessors后置处理器有机会返回代理对象而不是目标 bean 实例。如果能返回则直接使用,如果不能则调用 doCreateBean 方法来创建实例。
1 @Override 2 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 3 throws BeanCreationException { 4 /*现获取类的基本信息 例如: 5 Root bean: class [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]; 6 scope=singleton等等*/ 7 RootBeanDefinition mbdToUse = mbd; 8 //...... 9 //让beanPostProcessors有机会返回代理而不是目标bean实例。 10 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 11 if (bean != null) { 12 return bean; 13 } 14 //通过此方法,先调用 aware、前置处理器、bean初始化、后置处理器 ,之前有分析过。 15 Object beanInstance = doCreateBean(beanName, mbdToUse, args); 16 }
【BeanPostProcessor 是在 Bean 对象创建完成初始化前后调用的】
【InstantiationAwareBeanPostProcessor 是在创建 bean 实例之前先尝试用后置处理器返回代理对象】
后置处理器与后置处理器不同,具体什么时候调用,需要根据不同情况而定。
【2.1.1】分析 resolveBeforeInstantiation 方法(让 beanPostProcessors 有机会返回代理对象):我们分析的 AnnotationAwareAspectJAutoProxyCreator 就是 InstantiationAwareBeanPostProcessor 类型的后置处理器。会在任何 bean 创建之前先尝试返回 bean 的代理实例。
【2.1.1.1】接着分析上述的 postProcessBeforeInstantiation 方法:内容较多,放在五中分析。
【2.1.2】分析 doCreateBean 方法,之前有介绍过,我们在看下源码:就是对创建的目标类前后对后置处理器的方法进行初始化。才是真正创建一个 bean 的实例。
1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) 2 throws BeanCreationException { 3 //创建 bean 实例 4 instanceWrapper = createBeanInstance(beanName, mbd, args); 5 //bean 属性赋值 6 populateBean(beanName, mbd, instanceWrapper); 7 //初始化 bean 8 exposedObject = initializeBean(beanName, exposedObject, mbd); 9 } 10 11 12 //初始化方法 initializeBean 的源码 13 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { 14 //初始化 aware 接口的类 15 invokeAwareMethods(beanName, bean); 16 //后置处理器 Before 方法初始化 17 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 18 //初始化类 19 invokeInitMethods(beanName, wrappedBean, mbd); 20 //后置处理器 after 方法初始化 21 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 22 //返回创建好的类 23 return wrappedBean; 24 }
五、postProcessBeforeInstantiation 方法分析
【1】每个 bean 创建之前,调用此方法。我们主要观察业务逻辑 MathCalculator 类和切面 LogAspects 类的创建。
1 //当bean = MathCalculator or LogAspects 我们着重分析此方法,其他的略过 2 @Override 3 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { 4 Object cacheKey = getCacheKey(beanClass, beanName); 5 6 if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { 7 //判断当前 bean 是否在 advisedBeans 中(保存了所有需要增加的 bean:意思就是添加了切面的内容),第一次进行肯定是不包含的所以会跳过 8 if (this.advisedBeans.containsKey(cacheKey)) { 9 return null; 10 } 11 //isInfrastructureClass 判断当前类是否为基础类型的,也就是实现了 Advice、Pointcut、Advisor、AopInfrastructureBean 12 //或者是否为切面注解标注的类 (@Aspect),第一个 MathCalculator = false 13 //shouldSkip 是否需要跳过:内部是获取候选的增强器(也就是切面内的通知方法) 14 //将所有的增强器封装成了 List<Advisor> 集合,增强器的类型是 InstantiationModelAwarePointcutAdvisor 15 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { 16 this.advisedBeans.put(cacheKey, Boolean.FALSE); 17 return null; 18 } 19 } 20 // targetSource = null 21 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); 22 if (targetSource != null) { 23 if (StringUtils.hasLength(beanName)) { 24 this.targetSourcedBeans.add(beanName); 25 } 26 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); 27 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); 28 this.proxyTypes.put(cacheKey, proxy.getClass()); 29 return proxy; 30 } 31 //直接返回空,进入我们配置类中,创建 MathCalculator 对象 32 return null; 33 }
【2】上述代码中的 shouldSkip 源码:
1 @Override 2 protected boolean shouldSkip(Class<?> beanClass, String beanName) { 3 //获取所有的增强器 考虑通过缓存方面名称列表进行优化 4 List<Advisor> candidateAdvisors = findCandidateAdvisors(); 5 for (Advisor advisor : candidateAdvisors) { 6 //我们的增强器都是 InstantiationModelAwarePointcutAdvisor 类型的,不是AspectJPointcutAdvisor 所以跳过 7 if (advisor instanceof AspectJPointcutAdvisor && 8 ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) { 9 return true; 10 } 11 } 12 //父类直接返回 false 13 return super.shouldSkip(beanClass, beanName); 14 }
【3】创建完 MathCalculator 后,调用 postProcessAfterInitialization
【3.1】查看包装方法 wrapIfNecessary 的源码:分析后得出如下结论:以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程
【3.1.1】进入当前类使用的增强器方法:getAdvicesAndAdvisorsForBean
1 @Override 2 @Nullable 3 protected Object[] getAdvicesAndAdvisorsForBean( 4 Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { 5 //获取可用的增强器 6 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); 7 if (advisors.isEmpty()) { 8 return DO_NOT_PROXY; 9 } 10 return advisors.toArray(); 11 }
【3.1.1.1】进入获取可用增强器的方法:findEligibleAdvisors
【3.1.2】进入代理对象的创建方法:createProxy
【3.1.2.1】进入代理工厂创建对象的方法 proxyFactory.getProxy 的源码:
六、目标方法执行
【1】容器中保存了组件的代理对象(cglib 增强后的对象),这个对象里面保存了详细信息(比如:增强器,目标对象......)
【2】CglibAopProxy.intercept(); 拦截目标方法执行如下:主要是根据 ProxyFactory 对象获取将要执行的目标方法的拦截器链。
1)、如果没有拦截器链,直接执行目标方法。
2)、如果有拦截器链,吧需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation 对象,并调用 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); 方法。
1 @Override 2 @Nullable 3 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 4 Object oldProxy = null; 5 boolean setProxyContext = false; 6 Object target = null; 7 TargetSource targetSource = this.advised.getTargetSource(); 8 try { 9 if (this.advised.exposeProxy) { 10 oldProxy = AopContext.setCurrentProxy(proxy); 11 setProxyContext = true; 12 } 13 target = targetSource.getTarget(); 14 Class<?> targetClass = (target != null ? target.getClass() : null); 15 //根据 ProxyFactory 对象获取将要执行的目标方法的拦截器链 16 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 17 Object retVal; 18 //如果没有拦截器链,直接执行目标方法。 19 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { 20 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); 21 retVal = methodProxy.invoke(target, argsToUse); 22 } 23 //如果有拦截器链,吧需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation 对象,并调用如下方法。 24 else { 25 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); 26 } 27 retVal = processReturnType(proxy, target, method, retVal); 28 return retVal; 29 } 30 finally { 31 //...... 32 } 33 }
【3】 拦截器链:List<Object> chain = advised.getInterceptorsAndDynamicInterceptionAdvice 的源码展示:
1)、List<Object> interceptorList 中保存了所有拦截器,总计5个。一个默认的 ExposeInvocationInterceptor 和 4个增强器。
2)、遍历所有的增强器,将其转为 Interceptor(拦截器):registry.getInterceptors(advisor);
3)、将增强器转为 MethodInterceptor,转化方式如下:最终返回拦截器链(每一个通知方法又被包装为方法拦截器,后期都是利用 MethodInterceptor 机制)。
【4】、拦截器链有了之后,创建 CglibMethodInvocation 并执行 proceed 方法:
七、拦截器链的触发过程
【1】拦截器链展示:除了默认的方法 ExposeInvocationInterceptor 剩下的 4个都是我们切面中的方法。
【2】如果没有拦截器执行目标方法执行代理对象 CglibMethodInvocation 的 proceed 方法:
【3】进入 proceed 方法:
【4】进入 (MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); 方法:会循环调用 list 中的拦截器,直到后置处理器:AspectJMethodBeforeAdvice
【5】 当advice = AspectJMethodBeforeAdvice 后置处理器时,invoke 方法如下:
【7】 后置处理器的 After 方法执行的 invoke 方法展示:最终执行结果的返回方法。
【8】上述分析的流程图如下:根据链表循环向下执行,当最后一个后置处理器的 before 执行完成后,进行目标方法,并进行回流执行拦截器的目标方法。