飞道的博客

Spring源码------AOP源码分析

378人阅读  评论(0)

Spring源码------AOP源码分析

目录

Spring源码------AOP源码分析

1、AOP简介

2、AOP时序图

3、源码分析(简约版)

3.1 准备工作 

3.2 源码分析


1、AOP简介

AOP是什么?

AOP技术利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即切面。所谓“切面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

AOP相关概念

  • 方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现。
  • 连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
  • 通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice
  • 切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上
  • 目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。
  • AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

AOP原理

AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类

  • 静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强
  • 而动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强Spring AOP则采用的是动态代理来实现

2、AOP时序图

3、源码分析(简约版)

3.1 准备工作 

首先定义一个Spring AOP的配置文件spring-aop.xml


  
  1. <?xml version= "1.0" encoding= "UTF-8"?>
  2. <beans xmlns= "http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <aop:config>
  6. <aop:aspect id= "TestAspect" ref= "aspect">
  7. <aop:pointcut id= "pointcut" expression= "execution(* org.study.spring.aop.*.*(..))"/>
  8. <aop:before method= "doBefore" pointcut-ref= "pointcut"/>
  9. </aop:aspect>
  10. </aop:config>
  11. <bean id= "aspect" class= "org.study.spring.aop.Aspect"/>
  12. <bean id= "test" class= "org.study.spring.aop.TestAOP"/>
  13. </beans>

由于我们只分析JDK动态代理的实现方式,所以需要定义一个接口。


  
  1. public interface ITestAOP{
  2. public void doSomething();
  3. }

目标对象实现上面定义的接口。


  
  1. public class Test implements ITestAOP {
  2. public void doSomething() {
  3. System.out.println( "do something");
  4. }
  5. }

定义Aspect,这里我们以前置通知为例


  
  1. public class Aspect {
  2. public void doBefore(JoinPoint jp) {
  3. System.out.println( "do before");
  4. }
  5. }

编写程序入口代码,可以直接打断点进行调试。


  
  1. ApplicationContext context = new ClassPathXmlApplicationContext( "spring.xml");
  2. Test bean = context.getBean( "test", TestAOP.class);
  3. bean.doSomething();

3.2 源码分析

1.进入AbstractAutowireCapableBeanFactory的initializeBean()

   从源码中可以看到,AOP其实就是通过后置处理对bean的一种增强,而它用到的是代理技术


  
  1. //初始容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器
  2. protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
  3. //JDK的安全机制验证权限
  4. if (System.getSecurityManager() != null) {
  5. //实现PrivilegedAction接口的匿名内部类
  6. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  7. invokeAwareMethods(beanName, bean);
  8. return null;
  9. }, getAccessControlContext());
  10. }
  11. else {
  12. //为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
  13. invokeAwareMethods(beanName, bean);
  14. }
  15. Object wrappedBean = bean;
  16. //对BeanPostProcessor后置处理器的postProcessBeforeInitialization
  17. //回调方法的调用,为Bean实例初始化前做一些处理
  18. if (mbd == null || !mbd.isSynthetic()) {
  19. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  20. }
  21. //调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置
  22. //文件中通过init-method属性指定的
  23. try {
  24. invokeInitMethods(beanName, wrappedBean, mbd);
  25. }
  26. catch (Throwable ex) {
  27. throw new BeanCreationException(
  28. (mbd != null ? mbd.getResourceDescription() : null),
  29. beanName, "Invocation of init method failed", ex);
  30. }
  31. //对BeanPostProcessor后置处理器的postProcessAfterInitialization
  32. //回调方法的调用,为Bean实例初始化之后做一些处理
  33. if (mbd == null || !mbd.isSynthetic()) {
  34. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  35. }
  36. return wrappedBean;
  37. }

2. 在applyBeanPostProcessorsAfterInitialization方法上,

    按住Ctrl+鼠标左键进入applyBeanPostProcessorsAfterInitialization方法


  
  1. //调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法
  2. public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
  3. throws BeansException {
  4. Object result = existingBean;
  5. //遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器
  6. for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
  7. //调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在
  8. //初始化之后做一些自定义的处理操作
  9. Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
  10. if (current == null) {
  11. return result;
  12. }
  13. result = current;
  14. }
  15. return result;
  16. }

3. 在postProcessAfterInitialization方法上,

   按住Ctrl+Alt+B选择AbstractAutoProxyCreator进入postProcessAfterInitialization()


  
  1. @Override
  2. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
  3. if (bean != null) {
  4. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  5. if (! this.earlyProxyReferences.contains(cacheKey)) {
  6. return wrapIfNecessary(bean, beanName, cacheKey);
  7. }
  8. }
  9. return bean;
  10. }

4.wrapIfNecessary方法上,按住Ctrl+鼠标左键进入自身wrapIfNecessary方法


  
  1. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  2. if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
  3. return bean;
  4. }
  5. if (Boolean.FALSE.equals( this.advisedBeans.get(cacheKey))) {
  6. return bean;
  7. }
  8. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  9. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  10. return bean;
  11. }
  12. // 获取通知列表
  13. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  14. //判断是否有通知,如果有,继续进行代理
  15. if (specificInterceptors != DO_NOT_PROXY) {
  16. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  17. //创建代理对象
  18. Object proxy = createProxy(
  19. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  20. this.proxyTypes.put(cacheKey, proxy.getClass());
  21. return proxy;
  22. }
  23. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  24. return bean;
  25. }

从上面我们可以看到,Spring在这里先获取配置好的Advisor信息,然后调用createProxy方法为目标对象创建了代理,接着将创建的代理对象返回。

5. 在getAdvicesAndAdvisorsForBean方法上,按住Ctrl+Alt+B选择AbstractAdvisorAutoProxyCreatorgetAdvicesAndAdvisorsForBean


  
  1. protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
  2. //获取通知列表
  3. List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  4. if (advisors.isEmpty()) {
  5. return DO_NOT_PROXY;
  6. }
  7. return advisors.toArray();
  8. }
  9. protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  10. List<Advisor> candidateAdvisors = findCandidateAdvisors();
  11. List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  12. extendAdvisors(eligibleAdvisors);
  13. if (!eligibleAdvisors.isEmpty()) {
  14. eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  15. }
  16. return eligibleAdvisors;
  17. }
  18. protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
  19. AnnotationAwareOrderComparator.sort(advisors);
  20. return advisors;
  21. }
  22. public static void sort(List<?> list) {
  23. if (list.size() > 1) {
  24. Collections.sort(list, INSTANCE);
  25. }
  26. }

从上面可以知道,代理前需要先拿到通知的列表(包括前置通知,后置通知,异常通知等等)

6.按住Ctrl+Alt+左方向键返回到第4步的wrapIfNecessary方法,

    找到createProxy方法,按住Ctrl+鼠标左键进入createProxy方法


  
  1. protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
  2. @Nullable Object[] specificInterceptors, TargetSource targetSource) {
  3. if ( this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
  4. }
  5. ProxyFactory proxyFactory = new ProxyFactory();
  6. proxyFactory.copyFrom( this);
  7. if (!proxyFactory.isProxyTargetClass()) {
  8. if (shouldProxyTargetClass(beanClass, beanName)) {
  9. proxyFactory.setProxyTargetClass( true);
  10. }
  11. else {
  12. evaluateProxyInterfaces(beanClass, proxyFactory);
  13. }
  14. }
  15. Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  16. proxyFactory.addAdvisors(advisors);
  17. proxyFactory.setTargetSource(targetSource);
  18. customizeProxyFactory(proxyFactory);
  19. proxyFactory.setFrozen( this.freezeProxy);
  20. if (advisorsPreFiltered()) {
  21. proxyFactory.setPreFiltered( true);
  22. }
  23. return proxyFactory.getProxy(getProxyClassLoader());
  24. }

代理前各种属性操作------

8.直接进入JdkDynamicAopProxy 的 getProxy()方法


  
  1. /**
  2. * 获取代理类要实现的接口,除了Advised对象中配置的,还会加上SpringProxy, Advised(opaque=false)
  3. * 检查上面得到的接口中有没有定义 equals或者hashcode的接口
  4. * 调用Proxy.newProxyInstance创建代理对象
  5. */
  6. @Override
  7. public Object getProxy(@Nullable ClassLoader classLoader) {
  8. if (logger.isDebugEnabled()) {
  9. logger.debug( "Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
  10. }
  11. Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces( this.advised, true);
  12. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  13. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  14. }

看到这里,大家一定非常的兴奋,Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)不就是反射获取实例对象吗?没错,那么疑问来了,Aop切面是如何织入的呢?


 


9. 在proxyFactory.getProxy方法上,Ctrl+Alt+B进入ProxyFactorygetProxy方法


  
  1. protected final synchronized AopProxy createAopProxy() {
  2. if (! this.active) {
  3. activate();
  4. }
  5. return getAopProxyFactory().createAopProxy( this);
  6. }

10. 在createAopProxy(this)方法上,按住Ctrl+Alt+B进入DefaultAopProxyFactorycreateAopProxy方法
    从下面源码可以得出:会根据判断进入不同的代理模式


  
  1. @Override
  2. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  3. if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
  4. Class<?> targetClass = config.getTargetClass();
  5. if (targetClass == null) {
  6. throw new AopConfigException( "TargetSource cannot determine target class: " +
  7. "Either an interface or a target is required for proxy creation.");
  8. }
  9. //如果目标类实现的是接口,走jdk动态代理
  10. if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
  11. return new JdkDynamicAopProxy(config);
  12. }
  13. //cglib动态代理
  14. return new ObjenesisCglibAopProxy(config);
  15. }
  16. else {
  17. return new JdkDynamicAopProxy(config);
  18. }
  19. }

11.进入JdkDynamicAopProxyinvoke方法


  
  1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  2. MethodInvocation invocation;
  3. Object oldProxy = null;
  4. boolean setProxyContext = false;
  5. TargetSource targetSource = this.advised.targetSource;
  6. Object target = null;
  7. try {
  8. //eqauls()方法,具目标对象未实现此方法
  9. if (! this.equalsDefined && AopUtils.isEqualsMethod(method)) {
  10. // The target does not implement the equals(Object) method itself.
  11. return equals(args[ 0]);
  12. }
  13. //hashCode()方法,具目标对象未实现此方法
  14. else if (! this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
  15. // The target does not implement the hashCode() method itself.
  16. return hashCode();
  17. }
  18. else if (method.getDeclaringClass() == DecoratingProxy.class) {
  19. // There is only getDecoratedClass() declared -> dispatch to proxy config.
  20. return AopProxyUtils.ultimateTargetClass( this.advised);
  21. }
  22. //Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知
  23. else if (! this.advised.opaque && method.getDeclaringClass().isInterface() &&
  24. method.getDeclaringClass().isAssignableFrom(Advised.class)) {
  25. // Service invocations on ProxyConfig with the proxy config...
  26. return AopUtils.invokeJoinpointUsingReflection( this.advised, method, args);
  27. }
  28. Object retVal;
  29. if ( this.advised.exposeProxy) {
  30. oldProxy = AopContext.setCurrentProxy(proxy);
  31. setProxyContext = true;
  32. }
  33. //获得目标对象的类
  34. target = targetSource.getTarget();
  35. Class<?> targetClass = (target != null ? target.getClass() : null);
  36. //获取可以应用到此方法上的Interceptor列表
  37. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  38. //如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)
  39. if (chain.isEmpty()) {
  40. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  41. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  42. }
  43. else {
  44. //创建MethodInvocation
  45. invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  46. // Proceed to the joinpoint through the interceptor chain.
  47. retVal = invocation.proceed();
  48. }
  49. // Massage return value if necessary.
  50. Class<?> returnType = method.getReturnType();
  51. if (retVal != null && retVal == target &&
  52. returnType != Object.class && returnType.isInstance(proxy) &&
  53. !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
  54. // Special case: it returned "this" and the return type of the method
  55. // is type-compatible. Note that we can't help if the target sets
  56. // a reference to itself in another returned object.
  57. retVal = proxy;
  58. }
  59. else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
  60. throw new AopInvocationException(
  61. "Null return value from advice does not match primitive return type for: " + method);
  62. }
  63. return retVal;
  64. }
  65. finally {
  66. if (target != null && !targetSource.isStatic()) {
  67. // Must have come from TargetSource.
  68. targetSource.releaseTarget(target);
  69. }
  70. if (setProxyContext) {
  71. // Restore old proxy.
  72. AopContext.setCurrentProxy(oldProxy);
  73. }
  74. }
  75. }

这里有一个很重要的方法:获取可以应用到此方法上的Interceptor列表

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

  • 所以 按住Ctrl+Alt+B****getInterceptorsAndDynamicInterceptionAdvice方法,进入AdvisedSupportgetInterceptorsAndDynamicInterceptionAdvice方法

  
  1. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
  2. MethodCacheKey cacheKey = new MethodCacheKey(method);
  3. List<Object> cached = this.methodCache.get(cacheKey);
  4. if (cached == null) {
  5. cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
  6. this, method, targetClass);
  7. this.methodCache.put(cacheKey, cached);
  8. }
  9. return cached;
  10. }
  • 继续进入在advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice方法上,

      按住Ctrl+Alt+B进入DefaultAdvisorChainFactorygetInterceptorsAndDynamicInterceptionAdvice方法


  
  1. /**
  2. * 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,
  3. * 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断
  4. * 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.
  5. */
  6. @Override
  7. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
  8. Advised config, Method method, @Nullable Class<?> targetClass) {
  9. // This is somewhat tricky... We have to process introductions first,
  10. // but we need to preserve order in the ultimate list.
  11. List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
  12. Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
  13. //查看是否包含IntroductionAdvisor
  14. boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
  15. //这里实际上注册一系列AdvisorAdapter,用于将Advisor转化成MethodInterceptor
  16. AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
  17. for (Advisor advisor : config.getAdvisors()) {
  18. if (advisor instanceof PointcutAdvisor) {
  19. // Add it conditionally.
  20. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
  21. if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
  22. //这个地方这两个方法的位置可以互换下
  23. //将Advisor转化成Interceptor
  24. MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
  25. //检查当前advisor的pointcut是否可以匹配当前方法
  26. MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
  27. if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
  28. if (mm.isRuntime()) {
  29. // Creating a new object instance in the getInterceptors() method
  30. // isn't a problem as we normally cache created chains.
  31. for (MethodInterceptor interceptor : interceptors) {
  32. interceptorList.add( new InterceptorAndDynamicMethodMatcher(interceptor, mm));
  33. }
  34. }
  35. else {
  36. interceptorList.addAll(Arrays.asList(interceptors));
  37. }
  38. }
  39. }
  40. }
  41. else if (advisor instanceof IntroductionAdvisor) {
  42. IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
  43. if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
  44. Interceptor[] interceptors = registry.getInterceptors(advisor);
  45. interceptorList.addAll(Arrays.asList(interceptors));
  46. }
  47. }
  48. else {
  49. Interceptor[] interceptors = registry.getInterceptors(advisor);
  50. interceptorList.addAll(Arrays.asList(interceptors));
  51. }
  52. }
  53. return interceptorList;
  54. }

上面搞了这么多,就是为了拿到一条将通知封装成MethodInvoation的通知链,为了以下使用责任链模式进行invoke时可以顺序的织入所有的通知。继续搞下去:

12. 返回11步,进入invocation.proceed方法,进入到 ReflectiveMethodInvocation 的proceed() 方法


  
  1. Override
  2. @Nullable
  3. public Object proceed() throws Throwable {
  4. // We start with an index of -1 and increment early.
  5. //如果Interceptor执行完了,则执行joinPoint
  6. if ( this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
  7. return invokeJoinpoint();
  8. }
  9. Object interceptorOrInterceptionAdvice =
  10. this.interceptorsAndDynamicMethodMatchers.get(++ this.currentInterceptorIndex);
  11. //如果要动态匹配joinPoint
  12. if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
  13. // Evaluate dynamic method matcher here: static part will already have
  14. // been evaluated and found to match.
  15. InterceptorAndDynamicMethodMatcher dm =
  16. (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
  17. //动态匹配:运行时参数是否满足匹配条件
  18. if (dm.methodMatcher.matches( this.method, this.targetClass, this.arguments)) {
  19. return dm.interceptor.invoke( this);
  20. }
  21. else {
  22. // Dynamic matching failed.
  23. // Skip this interceptor and invoke the next in the chain.
  24. //动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
  25. return proceed();
  26. }
  27. }
  28. else {
  29. // It's an interceptor, so we just invoke it: The pointcut will have
  30. // been evaluated statically before this object was constructed.
  31. //执行当前Intercetpor
  32. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke( this);
  33. }
  34. }

13.进入dm.interceptor.invoke(this);按住Ctrl+Alt+B选择选择MethodBeforeAdviceInterceptor的invoke方法


  
  1. @Override
  2. public Object invoke(MethodInvocation mi) throws Throwable {
  3. this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
  4. return mi.proceed();
  5. }

14. 在.invoke(this)方法上,按住Ctrl+Alt+B选择AfterReturningAdviceInterceptorinvoke方法


  
  1. @Override
  2. public Object invoke(MethodInvocation mi) throws Throwable {
  3. Object retVal = mi.proceed();
  4. this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
  5. return retVal;
  6. }

从12、13、14可以知道Spring AOP多个通知的执行顺序应该像一个同心圆,

 

从12、13、14可以知道Spring AOP多个通知的执行顺序应该像一个同心圆:

spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小。从最外层按照AOP1、AOP2的顺序依次执行doAround方法,doBefore方法。然后执行method方法,最后按照AOP2、AOP1的顺序依次执行doAfter、doAfterReturn方法。也就是说对多个AOP来说,先before的,一定后after。

        如果我们要在同一个方法事务提交后执行自己的AOP,那么把事务的AOP order设置为2,自己的AOP order设置为1,然后在doAfterReturn里边处理自己的业务逻辑。

 


转载:https://blog.csdn.net/qqq3117004957/article/details/106087315
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场