Spring AOP MethodInvocation interceptors principle calls

Spring AOP source directory

Spring AOP Source 01: Jdk dynamic proxy for the underlying source
Spring AOP Source 02: the ProxyFactory
Spring AOP Source 03: JdkDynamicAopProxy
Spring AOP Source 04: MethodInvocation call interceptor
Spring AOP Source 05: The DefaultAdvisorAutoProxyCreator
the Spring finale final exam question: When Spring AOP met circular dependencies
Notes git source address: https: //github.com/chaitou/spring-framework-master.git

Foreword

By JdkDynamicAopProxythe invokemethods of inquiry and found that invokethe core is:

  1. Matching the current process advisor, for example, current methods to enhance the matched all before, afterReturning etc., then these enhanced composition interceptor chain
// 生产拦截器链
MethodInvocation invocation =
      new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 执行拦截器链
retVal = invocation.proceed();
  1. Call interceptor chain to enable it by before -> method -> after -> afterReturningorder of the chain of calls. But in the source code, we do not see for the cycle call, but only invoke(this)this line of critical code. And this is how to ensure that each line of code to enhance the orderly call it? We will take this issue to explore what interceptor source. A typical duty chain.
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) {
         // 省略动态匹配,不是本节重点 ...
      }
      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);
      }
}

Source code analysis

The sample code

Service、ServiceImpl

public interface UserService {
	public void findUser();
}

@Component
public class UserServiceImpl implements UserService {
	public void findUser() {
		System.out.println("findUser");
	}
}

Class of two facets of the order

@Component
@Aspect
public class LogAspect1 implements Ordered {

	@Pointcut("execution(* aop.UserServiceImpl.findUser())")
	public void point() {
	}

	@Before("point()")
	public void before(){
		System.out.println("log before1...");
	}

	@AfterReturning("point()")
	public void afterReturning() { System.out.println("log after returning1..."); }

	@Override
	public int getOrder() {
		return 1;
	}
}
@Component
@Aspect
public class LogAspect2 implements Ordered {

	@Pointcut("execution(* aop.UserServiceImpl.findUser())")
	public void point() {
	}

	@Before("point()")
	public void before(){
		System.out.println("log before2...");
	}

	@AfterReturning("point()")
	public void afterReturning() { System.out.println("log after returning2..."); }

	@Override
	public int getOrder() {
		return 2;
	}
}

xml configuration, auto scan, just open AOP

<context:component-scan base-package="aop" />
<aop:aspectj-autoproxy/>

test

	@Test
	public void test1() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop.xml");
		UserService userService = (UserService) applicationContext.getBean("userServiceImpl", UserService.class);
		userService.findUser();
	}

result

log before1...
log before2...
findUser
log after returning2...
log after returning1...

Implementation process

We can see the results already obtained, almost like the process of implementation of the interceptor stack, first before after after, probably shown below

aop call

Source code analysis

Production interceptor chain

// 生产拦截器链
MethodInvocation invocation =
      new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

First we look at the chain of interceptors look like in the end, through debugging code to view the invocationvariable
Interceptor chain

  1. The sort order has already done in the acquisition section, the next section we will see the source code, there is not tangled, is through a callback subclass getOrdergets the priority, and then sorted
  2. We see the same order, the afterReturingsurprise came in before, so how to ensure that beforethe aftercall before it?
  3. methodThe method is not in the list, but also when to call methodit?

The answer is an enhanced call control sequence is actually responsible for each interceptor, so we need to analyze MethodBeforeAdviceInterceptorandAfterReturningAdviceInterceptor

Interceptor chain execution

// 执行拦截器链
retVal = invocation.proceed();
public Object proceed() throws Throwable {
      // 初始currentInterceptorIndex为-1,每调用一次proceed就把currentInterceptorIndex+1
      if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
         // 当调用次数 = 拦截器个数时
         // 1. 触发当前method方法
         return invokeJoinpoint();
      }

      Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
      if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
         // 省略动态匹配,不是本节重点 ...
      }
      else {
         // It's an interceptor, so we just invoke it: The pointcut will have
         // been evaluated statically before this object was constructed.
         // 2. 普通拦截器,直接触发拦截器invoke方法
         return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
      }
}
  1. 当调用次数 = 拦截器个数When calling methodthe method, the reader may have doubts? Such methodmethods do not become final call yet? Would like to address this question is to look at the source code to resolve the interceptor, so read on
  2. General interceptor, the interceptor directly call the invokemethod, so the focus or source code interceptor. It involves three kinds of interceptors here MethodBeforeAdviceInterceptorand AfterReturningAdviceInterceptorwe will focus on the analysis. ExposeInvocationInterceptorEach interceptor chain will add the interceptor, the interceptor chain for the current exposure to the ThreadLocal, so under the same thread can share the interceptor chain, not the focus of this section will not go

MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

	private final MethodBeforeAdvice advice;

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		// 先调用before方法
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		// 继续链式调用
		return mi.proceed();
	}

}

AfterReturningAdviceInterceptor

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

   private final AfterReturningAdvice advice;

   @Override
   public Object invoke(MethodInvocation mi) throws Throwable {
      // 先进行链式调用
      Object retVal = mi.proceed();
      // 再调用afterReturning方法
      this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
      return retVal;
   }

}

See here do not know is not a little prospect of a solution, the order interceptor chain execution timing in each interceptor invokeimplementation method. beforeWill first perform adviceenhancement chained calls again, this is better understood and afteris the first implementation of chained calls, then call adviceenhancement method, which is a recursive process, where the soul of hand painted mountains, painted about calling sequence, I believe can help you understand. (Note: overlooked ExposeInvocationInterceptor interceptors, only care before and afterReturing)
Call interceptor principle

Published 42 original articles · won praise 43 · views 40000 +

Guess you like

Origin blog.csdn.net/chaitoudaren/article/details/105278762