首页 > 编程语言 >Spring AOP源码(四):具体执行流程 - 责任链模式

Spring AOP源码(四):具体执行流程 - 责任链模式

时间:2022-12-29 20:56:33浏览次数:73  
标签:Callback 对象 Spring Object 代理 CALLBACK 源码 CGLIB AOP

1、AOP动态代理的字节码文件

1.1、代理对象class的核心伪代码

  1 public class MathCalculator$$EnhancerBySpringCGLIB$$9bfe5203 extends MathCalculator implements SpringProxy, Advised, Factory {
  2     // 代理对象的属性是否已被绑定
  3     private boolean CGLIB$BOUND;
  4     public static Object CGLIB$FACTORY_DATA;
  5     // 线程变量,用来存储callbacks集合
  6     private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
  7     private static final Callback[] CGLIB$STATIC_CALLBACKS;
  8     private MethodInterceptor CGLIB$CALLBACK_0;
  9     private MethodInterceptor CGLIB$CALLBACK_1;
 10     private NoOp CGLIB$CALLBACK_2;
 11     private Dispatcher CGLIB$CALLBACK_3;
 12     private Dispatcher CGLIB$CALLBACK_4;
 13     private MethodInterceptor CGLIB$CALLBACK_5;
 14     private MethodInterceptor CGLIB$CALLBACK_6;
 15     
 16     //********** 1、静态代码块中执行CGLIB$STATICHOOK1(),并新建线程变量CGLIB$THREAD_CALLBACKS  *******//
 17     static {
 18         CGLIB$STATICHOOK1();
 19     }
 20     static void CGLIB$STATICHOOK1() {
 21         // 创建线程变量,用来存储callbacks
 22         CGLIB$THREAD_CALLBACKS = new ThreadLocal();
 23         // 被代理类的动态代理对象的 Class
 24         Class var0 = Class.forName("com.snails.aop.xml.service.MathCalculator$$EnhancerBySpringCGLIB$$9bfe5203");
 25         Class var1;
 26         var10000 = ReflectUtils.findMethods(new String[]{"add", "(Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;", "toString", "()Ljava/lang/String;"}, (var1 = Class.forName("com.snails.aop.xml.service.MathCalculator")).getDeclaredMethods());
 27         CGLIB$add$0$Method = var10000[0];
 28         
 29         // 创建代理类
 30         CGLIB$add$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;", "add", "CGLIB$add$0");
 31     }
 32     
 33     //*****************************  2、实例化代理对象,并填充代理对象的属性   ***************************//
 34     public Object newInstance(Callback[] var1) {
 35         // 初始化线程变量CGLIB$THREAD_CALLBACKS 
 36         CGLIB$SET_THREAD_CALLBACKS(var1);
 37         // 构造函数,将线程变量里的Callback[]元素赋值给代理对象的属性(CGLIB$CALLBACK_0 - CGLIB$CALLBACK_7)
 38         MathCalculator$$EnhancerBySpringCGLIB$$9bfe5203 var10000 = new MathCalculator$$EnhancerBySpringCGLIB$$9bfe5203();
 39         // 线程变量中的内容置空
 40         CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
 41         // 返回创建代理对象
 42         return var10000;
 43     }
 44     // 将Callback[]放入线程变量CGLIB$THREAD_CALLBACKS中
 45     public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
 46         CGLIB$THREAD_CALLBACKS.set(var0);
 47     }
 48     // 构造函数,填充代理对象的属性
 49     public MathCalculator$$EnhancerBySpringCGLIB$$9bfe5203() {
 50         CGLIB$BIND_CALLBACKS(this);
 51     }
 52     // 填充代理对象的属性
 53     private static final void CGLIB$BIND_CALLBACKS(Object var0) {
 54         MathCalculator$$EnhancerBySpringCGLIB$$9bfe5203 var1 = (MathCalculator$$EnhancerBySpringCGLIB$$9bfe5203)var0;
 55         if (!var1.CGLIB$BOUND) {
 56             var1.CGLIB$BOUND = true;
 57             // 构造函数中,获取代理对象线程变量中的Callback[]集合
 58             Object var10000 = CGLIB$THREAD_CALLBACKS.get();
 59             if (var10000 == null) {
 60                 var10000 = CGLIB$STATIC_CALLBACKS;
 61                 if (var10000 == null) {
 62                     return;
 63                 }
 64             }
 65             
 66             // 属性赋值
 67             Callback[] var10001 = (Callback[])var10000;
 68             var1.CGLIB$CALLBACK_6 = (MethodInterceptor)((Callback[])var10000)[6];
 69             var1.CGLIB$CALLBACK_5 = (MethodInterceptor)var10001[5];
 70             var1.CGLIB$CALLBACK_4 = (Dispatcher)var10001[4];
 71             var1.CGLIB$CALLBACK_3 = (Dispatcher)var10001[3];
 72             var1.CGLIB$CALLBACK_2 = (NoOp)var10001[2];
 73             var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];
 74             var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
 75         }
 76     }
 77     
 78     //*****************************  3、执行切入点方法add  ***************************//
 79     public final Integer add(Integer var1, Integer var2) throws NoSuchMethodException {
 80         // 获取CGLIB$CALLBACK_0属性 ,即获取Callback[]数组,位置为0的对象
 81         MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
 82         // 若代理对象属性未填充
 83         if (var10000 == null) {
 84             // 将Callbacks集合中的元素绑定到代理对象的属性中
 85             CGLIB$BIND_CALLBACKS(this);
 86             // 获取CGLIB$CALLBACK_0属性,即获取Callback[]数组,位置为0的对象
 87             var10000 = this.CGLIB$CALLBACK_0;
 88         }
 89         
 90         // 执行CALLBACK_0的intercept方法
 91         return var10000 != null ? (Integer)var10000.intercept(this, CGLIB$add$0$Method, new Object[]{var1, var2}, CGLIB$add$0$Proxy) : super.add(var1, var2);
 92     }
 93     
 94     // 设置callback回调详情
 95     public void setCallbacks(Callback[] var1) {
 96         this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
 97         this.CGLIB$CALLBACK_1 = (MethodInterceptor)var1[1];
 98         this.CGLIB$CALLBACK_2 = (NoOp)var1[2];
 99         this.CGLIB$CALLBACK_3 = (Dispatcher)var1[3];
100         this.CGLIB$CALLBACK_4 = (Dispatcher)var1[4];
101         this.CGLIB$CALLBACK_5 = (MethodInterceptor)var1[5];
102         this.CGLIB$CALLBACK_6 = (MethodInterceptor)var1[6];
103     }
104    
105     // 获取Callbacks集合
106     public Callback[] getCallbacks() {
107         CGLIB$BIND_CALLBACKS(this);
108         return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1, this.CGLIB$CALLBACK_2, this.CGLIB$CALLBACK_3, this.CGLIB$CALLBACK_4, this.CGLIB$CALLBACK_5, this.CGLIB$CALLBACK_6};
109     }
110 
111 }

1.2、代理对象class的执行流程图

  代理对象的字节码伪代码可用如下流程图概括

通过代理对象class的伪代码可以带出问题:

  1、Callback[] 是什么,在哪里做的初始化   2、代理对象this.CGLIB$CALLBACK_0 指的是哪个对象? AbstractAutoProxyCreator#wrapIfNecessary->AbstractAutoProxyCreator#createProxy-> ProxyFactory#getProxy->CglibAopProxy#getProxy->CglibAopProxy#getCallbacks

2、Callback[]详情

  常用动态代理:JDK动态代理、CGLIB动态代理。CGLIB动态代理需要设置Callback的信息做回调,要弄清楚Callback[]的详情,还需要对代理对象的创建过程做进一步的分析,在AOP源码(三):创建AOP相关的bean中,分析出被代理类的代理对象是在初始化的后置处理节点创建的,并找到创建被代理类代理对象的入口AbstractAutoProxyCreator#wrapIfNecessary中的createProxy方法。

2.1、创建代理对象的准备工作

2.1.1、创建代理对象准备工作

  AbstractAutoProxyCreator#createProxy 核心伪代码:
 1 // 创建代理对象的准备工作
 2 protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
 3       @Nullable Object[] specificInterceptors, TargetSource targetSource) {
 4    // 创建代理工厂
 5    ProxyFactory proxyFactory = new ProxyFactory();
 6     
 7    //================================       1、获取创建动态代理的方式     ================================ //
 8    // 使用CGLIB动态代理, 判断beanName对应的beanDefinition中的attribute 的 preserveTargetClass 是否为true,不设置默认为空
 9    if (shouldProxyTargetClass(beanClass, beanName)) {
10       proxyFactory.setProxyTargetClass(true);
11    }
12    // 使用代理接口  jdk动态代理
13    else {
14       // 判断采用何种方式创建代理对象,被代理类实现了接口。将实现的接口设置进代理工厂中;未实现接口,将ProxyTargetClass标识设置为true
15       evaluateProxyInterfaces(beanClass, proxyFactory);
16    }
17     
18    //================================     2、封装ExposeInvovationInterceptor为Advisor   ================================ //
19    // 构建Advisor, 此处主要是将ExposeInvovationInterceptor封装成Advisor对象,ExposeInvovationInterceptor相当于是责任链模式的控制器
20    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
21    proxyFactory.addAdvisors(advisors);
22   
23    // 实际创建代理对象
24    return proxyFactory.getProxy(getProxyClassLoader());
25 }

1、获取创建代理对象的方式

  获取创建动态代理创建方式的准备工作,为ProxyConfig的属性interfaces、proxyTargetClass赋值,用于后续的判断处理。   ProxyProcessorSupport#evaluateProxyInterfaces 核心代理如下:
 1 protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
 2    // 获取所有被代理类的实现的接口
 3    Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
 4    // 被代理类是否实现接口标识,默认为false
 5    boolean hasReasonableProxyInterface = false;
 6    // 若被代理类实现了有效的接口,将标识设置为true
 7    for (Class<?> ifc : targetInterfaces) {
 8        // IO容器的回调接口、内部引用依赖的接口不能作为有效的代理接口,需排除;被代理类实现的接口中,至少要有一个方法
 9       if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
10             ifc.getMethods().length > 0) {
11          // 用接口代理,也就是jdk
12          hasReasonableProxyInterface = true;
13          break;
14       }
15    }
16    // 将被代理类实现的所有有效接口填充进代理工厂中
17    if (hasReasonableProxyInterface) {
18       for (Class<?> ifc : targetInterfaces) {
19          proxyFactory.addInterface(ifc);
20       }
21    }
22    else {
23       // 若代理类未实现接口,将ProxyTargetClass属性设置为true
24       proxyFactory.setProxyTargetClass(true);
25    }
26 }

  被代理类MathCalculator未实现任何接口, 此处执行proxyFactory.setProxyTargetClass(true),下面我们来看看Spring是如何利用上面赋值好的interfaces、proxyTargetClass来选择哪种创建代理对象的方式。

  DefaultAopProxyFactory#createAopProxy 判断创建代理对象的核心伪代码:
 1 // 创建AOP的代理方式
 2 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
 3    // config.isProxyTargetClass() 是否使用Cglib的方式创建代理对象  在上面的准备工作中设置为true
 4    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
 5       // 从AdvisedSupport中获取目标类 类对象
 6       Class<?> targetClass = config.getTargetClass();
 7 
 8       // 判断目标类是否是接口 如果目标类是接口的话,则还是使用JDK的方式生成代理对象;如果目标类是Proxy类型 则还是使用JDK的方式生成代理对象
 9       if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
10          return new JdkDynamicAopProxy(config);
11       }
12       // 配置了使用Cglib进行动态代理或者目标类没有接口,那么使用Cglib的方式创建代理对象
13       return new ObjenesisCglibAopProxy(config);
14    }
15    else {
16       // 使用JDK的提供的代理方式生成代理对象
17       return new JdkDynamicAopProxy(config);
18    }
19 }

  通过ProxyProcessorSupport#evaluateProxyInterfaces的分析,已经知道AOPConfig中的ProxyTargetClass为true,同时被代理类MathCalculator未实现任何接口,选择Cglib的方式创建代理对象。

2、封装ExposeInvovationInterceptor为Advisor

2.2.2、创建代理对象

1、Enhancer创建代理对象

  CglibAopProxy#getProxy 创建动态代理核心伪代码
 1 // 获取代理对象
 2 public Object getProxy(@Nullable ClassLoader classLoader) {
 3     // 从advised中获取ioc容器中配置的target对象
 4     Class<?> rootClass = this.advised.getTargetClass();
 5     Class<?> proxySuperClass = rootClass;
 6         
 7     // 创建及配置Enhancer
 8     Enhancer enhancer = createEnhancer();
 9     
10     // 配置超类,代理类实现的接口,回调方法等
11     enhancer.setSuperclass(proxySuperClass);
12     enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
13     enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
14     enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
15     
16     // 获取callbacks
17     Callback[] callbacks = getCallbacks(rootClass);
18     Class<?>[] types = new Class<?>[callbacks.length];
19     for (int x = 0; x < types.length; x++) {
20      types[x] = callbacks[x].getClass();
21     }
22     enhancer.setCallbackTypes(types);
23     
24     // 通过 Enhancer 生成代理对象,并设置回调
25     return createProxyClassAndInstance(enhancer, callbacks);
26 }

2、获取代理对象的回调方法

  创建代理对象核心伪代码中,在getCallbacks(rootClass)步骤获取到Callback[]的信息,CglibAopProxy#getCallbacks 获取回调方法的核心伪代码:
 1 // 获取回调方法
 2 private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
 3    // false
 4    boolean exposeProxy = this.advised.isExposeProxy();
 5    // false
 6    boolean isFrozen = this.advised.isFrozen();
 7    // true
 8    boolean isStatic = this.advised.getTargetSource().isStatic();
 9 
10    // 创建一个调用AOP流程的拦截器 DynamicAdvisedInterceptor
11    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
12    
13    // 获取目标拦截器
14    Callback targetInterceptor;
15    targetInterceptor = (isStatic ?
16         new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
17         new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
18    // 获取目标分配器
19    Callback targetDispatcher = (isStatic ?
20          new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
21   
22    // 回调方法初始化
23    Callback[] mainCallbacks = new Callback[] {
24          aopInterceptor,  // Advice通知
25          targetInterceptor,  // 调用目标被代理类的方法
26          new SerializableNoOp(),  
27          targetDispatcher, this.advisedDispatcher,
28          new EqualsInterceptor(this.advised),
29          new HashCodeInterceptor(this.advised)
30    };
31 
32    Callback[] callbacks;
33    callbacks = mainCallbacks;
34       
35    return callbacks;
36 }

  我们来看看callbacks的详情

  代理对象创建的流程图

到此,可以回答上述的两个问题了:

1、Callback[] 是什么,在哪里做的初始化   Callback[]是通过Cglib方式创建代理对象的回调方法,在创建被代理类MatchCalculator的代理对象做的初始化。 2、代理对象this.CGLIB$CALLBACK_0 指的是哪个对象   在被代理类bean初始化阶段创建的代理对象 Callback[]在索引为0的位置对应的对象为CglibAopProxy#DynamicAdvisedInterceptor

3、AOP通知链控制器 -> ExposeInvocationInterceptor

AbstractAutoProxyCreator#postProcessBeforeInstantiation 在初始化代理对象的后置处理中创建代理对象前,获取通知器Advice执行getAdvicesAndAdvisorsForBean方法,代码流程如下 AbstractAutoProxyCreator#postProcessBeforeInstantiation -> AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean -> AbstractAdvisorAutoProxyCreator#findEligibleAdvisors -> AspectJAwareAdvisorAutoProxyCreator#extendAdvisors -> AspectJProxyUtils#makeAdvisorChainAspectJCapableIfNecessary AspectJProxyUtils#makeAdvisorChainAspectJCapableIfNecessary 核心伪代码如下
 1 // 在通知链的开始位置添加
 2 public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
 3    // advisors通知器如果为空,则说明不需要代理
 4    if (!advisors.isEmpty()) {
 5       // 判断是否为Before/After/Around/AfterReturning/AfterThrowing等通知
 6       boolean foundAspectJAdvice = false;
 7       for (Advisor advisor : advisors) {
 8          if (isAspectJAdvice(advisor)) {
 9             foundAspectJAdvice = true;
10             break;
11          }
12       }
13       // advisors中不包含ExposeInvocationInterceptor,在通知链的开始位置添加ExposeInvocationInterceptor
14       if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
15          advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
16          return true;
17       }
18    }
19    return false;
20 }

4、执行流程

  AOP流程执行入口为CglibAopProxy#DynamicAdvisedInterceptor#intercept,核心伪代码

 1 // AOP流程执行的入口
 2 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
 3    Object oldProxy = null;
 4    boolean setProxyContext = false;
 5    Object target = null;
 6    TargetSource targetSource = this.advised.getTargetSource();
 7    try {
 8       if (this.advised.exposeProxy) {
 9          // Make invocation available if necessary.
10          oldProxy = AopContext.setCurrentProxy(proxy);
11          setProxyContext = true;
12       }
13  
14       target = targetSource.getTarget();
15       Class<?> targetClass = (target != null ? target.getClass() : null);
16       
17       // 从advised中获取ExposeInvocationInterceptor的AOP通知
18       List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
19   
20       // 通过cglibMethodInvocation来启动advice通知
21       Object  retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
22       retVal = processReturnType(proxy, target, method, retVal);
23       return retVal;
24    }
25 }

  CglibMethodInvocation#proceed 核心伪代码:

 1 public Object proceed() throws Throwable {
 2    // currentInterceptorIndex从 -1开始,集合中通知器是不是都已经被执行
 3    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
 4       return invokeJoinpoint();
 5    }
 6    
 7    // 集合中还有Advice未被执行,获取下一个索引位置的Advice
 8    Object interceptorOrInterceptionAdvice =
 9          this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
10    
11    // 从子类CglibAopProxy#CglibMethodInvocation调用的父类,this为CglibAopProxy#CglibMethodInvocation实例
12    return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
13 
14 }

  传入的this为CglibAopProxy#CglibMethodInvocation对象:

  来看下DynamicAdvisedInterceptor父类ReflectiveMethodInvocation的拦截器通知集合interceptorsAndDynamicMethodMatchers详情:

总结:

  从拦截器通知集合interceptorsAndDynamicMethodMatchers索引为0的位置开始取Advisor对象,执行对应的Advisor的invoke方法,下面来看一看Advisor集合中实例的invoke方法。

4.1、ExposeInvocationInterceptor 责任链拦截器

  ExposeInvocationInterceptor作为Advisor集合中索引位置为0的Advice,第一个执行,invoke方法如下:
 1 // 线程变量 存储当前AOP调用的方法
 2 private static final ThreadLocal<MethodInvocation> invocation = new NamedThreadLocal<>("Current AOP method invocation");
 3 
 4 // ExposeInvocationInterceptor 的 invoke
 5 public Object invoke(MethodInvocation mi) throws Throwable {
 6    // 获取当前正在执行的AOP的方法
 7    MethodInvocation oldInvocation = invocation.get();
 8    // 将 CglibAopProxy#CglibMethodInvocation 对象放入,为了让AOP链能返回到起始流程,遍历下一个索引的Advisor
 9    invocation.set(mi);
10    try {
11       // 执行当前正在执行AOP的Advice的proceed方法,CglibMethodInvocation#proceed()方法
12       return mi.proceed();
13    }
14    finally {
15       // 线程变量值还原
16       invocation.set(oldInvocation);
17    }
18 }

  将CglibMethodInvocation放入线程变量中,返回AOP流程起始位置。

4.2、AspectJAfterThrowingAdvice 异常通知

  程序执行未出现异常,执行CglibMethodInvocation#proceed()方法,遍历Advisor获取下一个Advice,执行invoke。
 1 // AspectJAfterThrowingAdvice的invoke
 2 public Object invoke(MethodInvocation mi) throws Throwable {
 3    try {
 4       // 程序执行未出现异常,执行CglibMethodInvocation#proceed()方法
 5       return mi.proceed();
 6    }
 7    catch (Throwable ex) {
 8        // 出现异常,执行在配置中定义的异常处理逻辑
 9       if (shouldInvokeOnThrowing(ex)) {
10          //  从ExposeInvocationInterceptor中获取当前正在执行AOP的Advice,并执行切面方法
11          invokeAdviceMethod(getJoinPointMatch(), null, ex);
12       }
13       throw ex;
14    }
15 }

4.3、AspectJAfterReturningAdvice 后置返回通知

1 // AspectJAfterReturningAdvice 的 invoke
2 public Object invoke(MethodInvocation mi) throws Throwable {
3    // 执行  CglibMethodInvocation#proceed()方法
4    Object retVal = mi.proceed();
5    // 处理完Around、Before、After通知后,执行AspectJAfterReturningAdvice的afterReturning方法
6    this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
7    return retVal;
8 }

4.4、AspectJAfterAdvice 后置通知

 1 // AspectJAfterAdvice 的 invoke
 2 public Object invoke(MethodInvocation mi) throws Throwable {
 3    try {
 4       // 执行  CglibMethodInvocation#proceed()方法
 5       return mi.proceed();
 6    }
 7    finally {
 8       // 处理完Around、Before通知后,调用配置通知After的相关方法
 9       invokeAdviceMethod(getJoinPointMatch(), null, null);
10    }
11 }

4.5、AspectJAroundAdvice 环绕通知

  在Around通知中,发现没有mi.proceed()方法,而是直接执行Advice通知的方法
 1 // AspectJAroundAdvice 的 invoke
 2 public Object invoke(MethodInvocation mi) throws Throwable {
 3    if (!(mi instanceof ProxyMethodInvocation)) {
 4       throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
 5    }
 6    // 类型强转为 ProxyMethodInvocation
 7    ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
 8    ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
 9    // 匹配节点
10    JoinPointMatch jpm = getJoinPointMatch(pmi);
11    // 执行Around的通知,执行定义的环绕通知
12    return invokeAdviceMethod(pjp, jpm, null, null);
13 }

  通常在自定义的Around方法中,都会看见pjp.proceed(args);的代码片段,这个代码段和 mi.proceed(); 有一样的作用,代表着回到CglibMethodInvocation#proceed方法中,继续获取Advisors中的Advice对象,Advisors中下一个Advice对应的Before通知。

 1 // 自定义的环绕通知
 2 public Object around(ProceedingJoinPoint pjp) throws Throwable {
 3    Signature signature = pjp.getSignature();
 4    Object[] args = pjp.getArgs();
 5    Object result = null;
 6    try {
 7       System.out.println("log---Around环绕通知start:"+signature.getName()+"方法开始执行,参数为:"+Arrays.asList(args));
 8       //通过反射的方式调用目标的方法,相当于执行method.invoke(),继续获取Advisors中下一个Advice
 9       result = pjp.proceed(args);
10       System.out.println("log---Around环绕通知stop"+signature.getName()+"方法执行结束");
11    } catch (Throwable throwable) {
12       System.out.println("log---Around环绕异常通知:"+signature.getName()+"出现异常");
13       throw throwable;
14    }
15    return result;
16 }

4.5、AspectJBeforeAdvice 前置通知

1 // AspectJBeforeAdvice 的invoke
2 @Override
3 public Object invoke(MethodInvocation mi) throws Throwable {\
4    // 执行前置通知,定义的前置通知方法
5    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
6    // 执行  CglibMethodInvocation#proceed()方法
7    return mi.proceed();
8 }
  AspectJBeforeAdvice中,自定义的前置通知执行完成后,再次执行执行 CglibMethodInvocation#proceed()方法,此时Advisors中的所有Advice通知都已经被执行到,CglibMethodInvocation的当前索引下标currentInterceptorIndex与interceptorsAndDynamicMethodMatchers中元素个数相同,此时执行被增强的方法(此例为add方法)。

4.6、AOP执行流程图

 

标签:Callback,对象,Spring,Object,代理,CALLBACK,源码,CGLIB,AOP
From: https://www.cnblogs.com/RunningSnails/p/17013513.html

相关文章

  • 自定义注解 + AOP切面 (切面不生效)
    背景业务开发,需要做一个操作日志,操作日志需要记录某一条数据在操作前后的值的变化记录,并写到操作记录表。这种情况,使用自定义注解,加个切面,再合适不过了。于是就开干。......
  • Springoot - 整合MyBatis
    1.导入JDBC驱动因为我的是Mysql数据库版本是8.0.20导入对应版本的驱动即可<!--mysql依赖--><dependency><groupId>mysql</groupId>......
  • 从Spring中学到的【2】--容器类
    容器类我们在实际编码中,常常会遇到各种容器类,他们有时叫做POJO,有时又叫做DTO,VO,DO等,这些类只具有容器的作用,具有完全的get,set方法,作为信息载体,作数据传输用。其实,很多地......
  • Nacos1.4源码(2):服务端注册源码
    注册表结构在先说注册源码之前,先要对注册表结构有一个印象,注册表结构如下:最外层使用NameSpace用来隔离环境NameSpace下有不同的Group,Group用来管理ServiceService下......
  • SpringBoot - WebMvcConfigurer 配置类
    WebMvcConfigurer:1.publicvoidconfigurePathMatch(PathMatchConfigurerconfigurer)路径匹配规则一般不用修改2.publicvoidconfigureContentNegotiation(ContentNe......
  • SpringBoot - 内容协商机制
    1.内容协商机制根据客户端接收能力不同,SpringBoot返回不同媒体类型的数据比如:客户端Http请求Accept:application/xml则返回xml数据,客户端Http请求Accept:a......
  • Spring声明式事务配置管理方法
    事务配置首先在/WEB-INF/applicationContext.xml添加以下内容:<!--配置事务管理器--><beanid="transactionManager"class="org.springframework.orm.hibernate3.Hibernat......
  • spring aop学习记录文档
    ProxyFactory:https://www.cnblogs.com/5207/p/6055152.htmlProxyConfig:https://www.cnblogs.com/mayang2465/p/12141814.htmlProxyFactory:https://juejin.cn/post/704079......
  • 源码:ConfigurationClassParser
    /**Copyright2002-2017theoriginalauthororauthors.**LicensedundertheApacheLicense,Version2.0(the"License");*youmaynotusethisfileexcept......
  • SpringBoot 的属性配置文件
    0、概述本文内容会解答下面几个问题:1、SpringBoot默认配置文件的名称是什么?配置文件默认存放位置是什么?2、如何指定配置文件名称?如何指定配置文件存放位置?3、如何使用pro......