天天看點

Spring AOP 源碼解讀

應用場景

公共子產品抽象出來,簡單的AOP功能編織到子產品中

核心技術實作

動态代理,相關的攔截器都配置到了動态對象裡

JDK 動态代理

隻能代理實作接口的類

invoke裡封裝了aop的實作

CGLIB 位元組碼增強技術

可以直接代理類

對callback回調設定中,通過DynamicAdvisedInterceptor攔截器來實作AOP功能的

源碼解析

以JDK動态代理為例

JdkDynamicAopProxy

@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			 //如果攔截器鍊為空,直接調用目标方法
			if (chain.isEmpty()) {
				// We can skip creating a MethodInvocation: just invoke the target directly
				// Note that the final invoker must be an InvokerInterceptor so we know it does
				// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// We need to create a method invocation...
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				//否則的話,從這裡開始調用
				retVal = invocation.proceed();
			}
	}
           

invocation 這個的實作ReflectiveMethodInvocation 這個類

@Override
	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;
		    //比對這個方法是不是需要攔截,是的話,調用攔截器
			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {               //invoke執行攔截器
				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);
		}
	}

           

上面有一個問題,從邏輯來看,是調用了所有的攔截器,再調用目标方法,這個時候,有一個疑問,after 通知不是方法執行了,再調用這個攔截操作嘛,繼續往下看

before 攔截器的實作 MethodBeforeAdviceInterceptor

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

after的實作 AspectJAfterAdvice

@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		finally {
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}
           

我們可以看到before和after有可差別的,before先執行攔截,再調用下一步的攔截,after是一直要調用目标方法執行了之後,才執行這個after的邏輯。這後邊是遞歸的邏輯。