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 JdkDynamicAopProxy
the invoke
methods of inquiry and found that invoke
the core is:
- 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();
- Call interceptor chain to enable it by
before -> method -> after -> afterReturning
order of the chain of calls. But in the source code, we do not see for the cycle call, but onlyinvoke(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
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 invocation
variable
- 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
getOrder
gets the priority, and then sorted - We see the same order, the
afterReturing
surprise came inbefore
, so how to ensure thatbefore
theafter
call before it? method
The method is not in the list, but also when to callmethod
it?
The answer is an enhanced call control sequence is actually responsible for each interceptor, so we need to analyze MethodBeforeAdviceInterceptor
andAfterReturningAdviceInterceptor
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);
}
}
当调用次数 = 拦截器个数
When callingmethod
the method, the reader may have doubts? Suchmethod
methods 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- General interceptor, the interceptor directly call the
invoke
method, so the focus or source code interceptor. It involves three kinds of interceptors hereMethodBeforeAdviceInterceptor
andAfterReturningAdviceInterceptor
we will focus on the analysis.ExposeInvocationInterceptor
Each 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 invoke
implementation method. before
Will first perform advice
enhancement chained calls again, this is better understood and after
is the first implementation of chained calls, then call advice
enhancement 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)