• Spring Aop 源码 (三) (执行过程)


    1.执行入口

    在这里插入图片描述

    在这里插入图片描述

    调用了CglibAopProxy.DynamicAdvisedInterceptor.intercept() 方法

    在这里插入图片描述

    在这里插入图片描述

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

    这个方法得到一个拦截器链, 是5个增强器封装成MethodInterceptor

    在这里插入图片描述

    然后 mi.proceed() 方法触发拦截器链的方法。

    在这里插入图片描述

    	@Override
    	@Nullable
    	public Object proceed() throws Throwable {
    		// We start with an index of -1 and increment early.
    		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    			return invokeJoinpoint();
    		}
    
    		Object interceptorOrInterceptionAdvice =
    				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
    			// Evaluate dynamic method matcher here: static part will already have
    			// been evaluated and found to match.
    			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 {
    				// Dynamic matching failed.
    				// Skip this interceptor and invoke the next in the chain.
    				return proceed();
    			}
    		}
    		else {
    			// It's an interceptor, so we just invoke it: The pointcut will have
    			// been evaluated statically before this object was constructed.
    			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    最后的一个方法进入了 invoke(this), 进入了拦截器的责任链

    2.进入拦截器责任链

    1. ReflectiveMethodInvocation.proceed() ->
    2. ExposeInvocationInterceptor.invoke(mi) -> currentInterceptorIndex = 1
    3. MethodBeforeAdviceInterceptor.invoke(this) -> advice.before -> mi.proceed -> currentInterceptorIndex = 2
    4. AspectJAfterAdvice.invoke(this) -> return mi.proceed() -> finally invokeAdviceMethod -> currentInterceptorIndex = 3
    5. AfterReturningAdviceInterceptor.invoke(this) -> Object retVal = mi.proceed() -> this.advice.afterReturning(retVal) -> return retVal -> currentInterceptorIndex =4
    6. AspectJAfterThrowingAdvice.invoke(this) -> return mi.proceed() -> catch invokeAdviceMethod
    7. invokeJoinPoint() 执行连接点, 执行目标方法

    在这里插入图片描述

    ExposeInvocationInterceptor, MethodBeforeAdviceInterceptor, AspectJAfterAdvice, AfterReturningAdviceInterceptor, AspectJAfterThrowingAdvice为Filter类

    CglibMethodInvocation 为 FilterChain

    在这里插入图片描述

    2.1 ExposeInvocationInterceptor

    这个拦截器为暴露共享数据

    在这里插入图片描述

    ExposeInvocationInterceptor.invoke()

    先是 invocation.set(mi); 这里的invocation是一个threadLocal, 可以保存共享数据

    在这里插入图片描述

    又进入了ReflectiveMethodInvocation.proceed()

    2.2 MethodBeforeAdviceInterceptor

    前置通知拦截器

    MethodBeforeAdviceInterceptor.invoke()

    在这里插入图片描述

    先是执行了前置通知, 然后返回mi.procced()

    2.3 AspectJAfterAdvice

    后置通知拦截器

    AspectJAfterAdvice.invoke()

    在这里插入图片描述
    返回的是 mi.proceed(), 并进行 invokeAdviceMethod()

    2.4 AfterReturningAdviceInterceptor

    返回通知拦截器

    AfterReturningAdviceInterceptor.invoke()

    在这里插入图片描述

    2.5 AspectJAfterThrowingAdvice

    异常通知

    AspectJAfterThrowingAdvice.invoke()

    在这里插入图片描述

    2.6 invokeJoinPoint()

    执行连接点, 用于执行方法

    在这里插入图片描述

    3.执行顺序

    前置通知 => 目标方法 => 返回通知 => 后置通知

    前置通知 => 目标方法 => 异常通知 => 后置通知

    try{
    	前置通知
    	目标方法
    	返回通知
    }catch(){
    	异常通知
    }finally{
    	后置通知
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    04.函数
    一文带您了解云渲染
    js实现星空雨随鼠标移动
    挂耳式耳机哪种好、适合户外运动的耳机推荐
    (附源码)springboot宠物领养系统 毕业设计 241104
    cpp层直接操作 surface
    差值结构的加法
    [4G/5G/6G专题基础-160]: BLER与MCS的关系
    LVGL 模拟仿真(Windows+CodeBlocks)
    二、基于PCL的RANSAC拟合点云中所有直线或平面——3D点云处理系列
  • 原文地址:https://blog.csdn.net/qq_43141726/article/details/127433162