通过@Transational注解的对象,简单了解SpringAop是如何执行的

5 阅读2分钟

从一个问题引入Aop的代理对象:假如你的一个方法上,同时有@Transational注解和@Retryable注解,这个时候Spring会生成几个代理对象?

是生成两个,切点被命中的时候,调用不同的代理对象? 还是只生成一个?如果只生成一个代理对象,它上面有两个注解,怎么知道对应要用哪个增强,还是都要用?

我们直接放结论

  1. 只会生成一个代理对象
  2. 两个注解会被包装成切点,类似:"annotation("@Transational")"和"annotation("@Retryable")"
  3. 你的切面,则会被包装成MethodIntercept,假如你有两个注解,则会有两个MethodIntercept拦截器
  4. 然后会在BeanPostProcess的after阶段,把类的切点解析出来,取出对应的切面,也就是拦截器
  5. 最后在执行的时候,通过责任链模式,去执行这个类下所有的切面,进行增强

下面看一下源码

这里是CglibAopProxy的intercept方法:

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
				target = targetSource.getTarget();
				Class<?> targetClass = (target != null ? target.getClass() : null);
                                //这里根据类和方法,获取到它所有的执行链
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				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...
					retVal = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain).proceed();
				}
				return processReturnType(proxy, target, method, args, retVal);
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}
// ReflectiveMethodInvocation的proceed方法
public Object proceed() throws Throwable {
		// We start with an index of -1 and increment early.
                // 方法在这里判断是否执行了所有的链,执行完了,再执行target的方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher dm) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
			if (dm.matcher().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);
		}
	}