目录
一、简介
在前面一篇文章中,我们介绍了 AOP 代理的创建过程,那么代理对象是创建出来了,在什么时候使用呢?通知方法又是在何处被调用了?
带着这些问题,我们以前面的AOP示例代码,边调试边介绍AOP代理的方法的完整执行过程。
二、AOP执行流程
先回顾一下前面使用AOP的切面代码:
// @Aspect:告诉Spring这是一个切面类
@Aspect
@Component
public class SimpleAspect {
// 定义切入点表达式
@Pointcut("execution(* com.wsh.service..*.*(..))")
private void pointcut() {
}
// 环绕通知
@Around("pointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws InterruptedException {
String methodName = proceedingJoinPoint.getSignature().getName();
System.out.println("执行" + methodName + "的环绕通知(@Around)...");
try {
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println(methodName + "()方法耗时: " + (endTime - startTime) + "毫秒");
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
}
// 前置通知
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行" + methodName + "的前置通知(@Before)...");
}
// 后置通知
@After("pointcut()")
public void after(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行" + methodName + "的后置通知(@After)...");
}
// 返回通知
@AfterReturning("pointcut()")
public void afterReturning(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行" + methodName + "的后置返回通知(@AfterReturning)...");
}
}
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("新增用户...");
}
}
当我们调用了被 AOP 代理的方法时,在本例中就是执行addUser()方法,使用 JDK 动态代理会走到 JdkDynamicAopProxy#invoke 方法,使用 CBLIB 代理会走到 DynamicAdvisedInterceptor#intercept 方法,两者的内容基本一样。
这里就以更常见的 JdkDynamicAopProxy#invoke 方法来介绍。
源码如下:
// org.springframework.aop.framework.JdkDynamicAopProxy.invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
// 1.获取到目标对象,也就是被代理对象的引用
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 如果目标对象未实现equals()方法,则不需要代理
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
// 如果目标对象未实现hashCode()方法,则不需要代理
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
// 如果方法是DecoratingProxy类型,也不需要拦截器执行
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 如果是Advised接口或者其父接口中定义的方法,则直接反射调用,不应用通知
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// 2. 如果exposeProxy属性值为true,则将代理对象暴露到ThreadLocal中
// exposeProxy是通过注解@EnableAspectJAutoProxy(exposeProxy = true)进行指定的,如果配置为true,
// 则可以使用AopContext.currentProxy()获取到代理对象. 在Spring事务方法自调用的时候经常使用到.
if (this.advised.exposeProxy) {
// 将代理对象暴露到ThreadLocal中
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 3.获得目标对象实例
target = targetSource.getTarget();
// 获取目标对象的类型
Class<?> targetClass = (target != null ? target.getClass() : null);
// 4.获得目标方法对应的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 5.如果对应的拦截器链为空,也就是没有可以应用到此方法的通知(Interceptor),则直接通过反射方式进行调用 ==> method.invoke(target, args)
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 {
// 6.如果拦截器链不为空,则需要创建一个MethodInvocation(方法调用对象)
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 调用其proceed方法,实际上是调用ReflectiveMethodInvocation.proceed()方法
retVal = invocation.proceed();
}
// 7.必要时转换返回值
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
// 恢复ThreadLocal中的旧代理对象
AopContext.setCurrentProxy(oldProxy);
}
}
}
invoke()方法的处理流程大体如下:
- 获取到目标对象,也就是被代理对象的引用;
- 处理exposeProxy属性,如果exposeProxy属性值为true,则将代理对象暴露到ThreadLocal中;
- 获得目标方法对应的拦截器链;
- 如果对应的拦截器链为空,也就是没有可以应用到此方法的通知(Interceptor),则直接通过反射方式进行调用;
- 如果拦截器链不为空,则需要创建一个MethodInvocation(方法调用对象),调用其proceed方法,实际上是调用ReflectiveMethodInvocation.proceed()方法;
- 有需要的话,转换返回值;
invoke()方法内部有三个比较重要的方法:
- getInterceptorsAndDynamicInterceptionAdvice():获得目标方法对应的拦截器链
// org.springframework.aop.framework.AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
// 1、首先从缓存中查找是否存在拦截器链
// private transient Map<MethodCacheKey, List<Object>> methodCache; 存放方法Method ==> 拦截器链集合的对应关系
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 2、如果缓存中不存在拦截器链,则委托getInterceptorsAndDynamicInterceptionAdvice()方法继续查找
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
// 3、将前面一个步骤找到的拦截器链存入缓存中
this.methodCache.put(cacheKey, cached);
}
// 4、如果缓存中存在拦截器链的话,则直接返回
return cached;
}
首先从缓存中查找是否存在拦截器链,如果存在的话,直接获取到并返回;如果获取不到,则委托getInterceptorsAndDynamicInterceptionAdvice()方法继续查找,在本例子,因为第一次进来,缓存中肯定没有,所以走的是getInterceptorsAndDynamicInterceptionAdvice()方法:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
// 使用单例模式创建DefaultAdvisorAdapterRegistry实例
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 从config中获取所有的advisors增强器
Advisor[] advisors = config.getAdvisors();
// 保存拦截器集合,长度就是增强器的总数量
List<Object> interceptorList = new ArrayList<>(advisors.length);
// 目标类
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
// 判断是否包含IntroductionAdvisor类型的增强器
Boolean hasIntroductions = null;
// 遍历advisors数组,根据不同类型的Advisor做不同的处理
for (Advisor advisor : advisors) {
// 如果advisor是PointcutAdvisor类型,判断advisor能否应用到目标方法
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
// 检查当前advisor的pointcut是否可以匹配当前方法
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
} else {
match = mm.matches(method, actualClass);
}
// 如果匹配的话,将增强器转换成MethodInterceptor拦截器对象
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 如果advisor是IntroductionAdvisor类型,判断advisor能否应用到目标类
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
首先获取到所有的增强器,然后循环遍历,根据不同类型的Advisor做不同的处理。在本例中,增强器都是PointcutAdvisor类型,接着会MethodMatcher#match()方法检查当前advisor的pointcut是否可以匹配当前方法。如果匹配的话,则将增强器转换成MethodInterceptor拦截器对象。
具体逻辑在DefaultAdvisorAdapterRegistry#getInterceptors()方法:
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
// 如果是MethodInterceptor类型的通知,则直接加入集合中
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
// 通过适配器将advisor转换为MethodInterceptor拦截器
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(将advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
执行完getInterceptorsAndDynamicInterceptionAdvice()方法后,已经将Advisor增强器转换为了MethodInterceptor对象,如下图:
接着,Spring会将获取到的MethodInterceptor对象存入缓存,以便下次可以从缓存中直接获取。
- invokeJoinpointUsingReflection():通过反射方式调用目标方法
处理过程比较简单,就是通过method.invoke()反射调用目标方法的过程,源码如下:
// org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection
// 通过反射方式调用目标方法
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
try {
// 设置可访问权限
ReflectionUtils.makeAccessible(method);
// 使用反射调用目标方法
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}
- MethodInvocation#proceed():执行拦截器链方法
在本例子中,目标方法对应的拦截器链不为空,所以需要根据代理对象、被代理对象、目标方法、目标方法的执行参数、拦截器链实例化一个MethodInvocation方法执行对象。
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain)
接着调用MethodInvocation#proceed方法,实际上是调用ReflectiveMethodInvocation.proceed()方法。这里就开始拦截器链的执行流程了,Spring使用了责任链模式实现。
// ReflectiveMethodInvocation.proceed()
// 开始执行拦截器链增强方法
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 1.当前拦截器下标:从-1的位置开始, 直到满足索引下标 =(拦截器的长度 -1)的条件(所有拦截器都执行完毕),此时需要执行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 执行目标方法
return invokeJoinpoint();
}
// 2.每次调用时,将索引的值递增,从拦截器链中获取下一个需要执行的拦截器
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 {
// 如果匹配失败,则会跳过当前拦截器interceptor,则会调用proceed()方法执行拦截器链中的下一个拦截器的处理
return proceed();
}
} else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 3.只是一个普通的拦截器,则触发拦截器链责任链的调用,并且参数为ReflectiveMethodInvocation本身
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
proceed()方法的执行流程大体如下:
- 判断是否所有的拦截器已经执行完成,从-1(当前拦截器下标)的位置开始, 直到满足索引下标 =(拦截器的长度 -1)的条件(即所有拦截器都执行完毕),此时需要执行目标方法(在本例中就是执行addUser()方法);
- 每次调用时,将索引的值递增,从拦截器链中获取下一个需要执行的拦截器;
- 判断是否是InterceptorAndDynamicMethodMatcher动态方法匹配拦截器类型还是普通拦截器类型,分别做不同的处理;
我们继续跟踪代码:
这里我们的的拦截器总共有五个,如下图:
所以this.interceptorsAndDynamicMethodMatchers.size() - 1 = 4,每次进来proceed()方法都会执行如下判断:
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 执行目标方法
return invokeJoinpoint();
}
(1)、proceed()方法第一次进来: 当前拦截器索引为-1,-1 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(0)获取到第一个拦截器:也就是默认的ExposeInvocationInterceptor拦截器,ExposeInvocationInterceptor只是一个普通的拦截器,则触发拦截器链责任链的调用,执行invoke()方法;
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
// 将MethodInvocation对象存入ThreadLocal中
invocation.set(mi);
try {
// 执行链中下一个拦截器的逻辑
return mi.proceed();
} finally {
// 重置原来的MethodInvocation
invocation.set(oldInvocation);
}
}
当执行到mi.proceed()时,会执行链中下一个拦截器的逻辑,这时候实际又回到ReflectiveMethodInvocation#proceed()方法执行。
(二)、proceed()方法第二次进来: 当前拦截器索引为0,0 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(1)获取到第二个拦截器:也就是AfterReturningAdviceInterceptor拦截器,AfterReturningAdviceInterceptor也是一个普通的拦截器,则触发拦截器链责任链的调用,执行AfterReturningAdviceInterceptor.invoke()方法:
// org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
// 这里没有try-catch,如果方法是异常退出的话,则不会调用@AfterReturning通知方法
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
当执行到mi.proceed()时,会执行链中下一个拦截器的逻辑,这时候实际又回到ReflectiveMethodInvocation#proceed()方法执行。
(三)、proceed()方法第三次进来: 当前拦截器索引为1,1 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(2)获取到第三个拦截器:也就是AspectJAfterAdvice拦截器,AspectJAfterAdvice也是一个普通的拦截器,则触发拦截器链责任链的调用,执行AspectJAfterAdvice.invoke()方法:
// org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 调用下一个拦截器的逻辑
return mi.proceed();
} finally {
// 不管方法正常退出还是异常退出,都会调用@After通知方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
当执行到mi.proceed()时,会执行链中下一个拦截器的逻辑,这时候实际又回到ReflectiveMethodInvocation#proceed()方法执行。
(四)、proceed()方法第四次进来: 当前拦截器索引为2,2 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(3)获取到第四个拦截器:也就是AspectJAroundAdvice拦截器,AspectJAroundAdvice也是一个普通的拦截器,则触发拦截器链责任链的调用,执行AspectJAroundAdvice.invoke()方法:
// org.springframework.aop.aspectj.AspectJAroundAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
// 拿到pointcut切入点表达式
JoinPointMatch jpm = getJoinPointMatch(pmi);
// 执行通知方法进行增强
return invokeAdviceMethod(pjp, jpm, null, null);
}
// org.springframework.aop.aspectj.AbstractAspectJAdvice#invokeAdviceMethod()
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
// argBinding(): 获取方法执行连接点处的参数
// invokeAdviceMethodWithGivenArgs(): 使用给定的参数调用增强方法
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
// 如果通知方法不包含参数,则将actualArgs置为null
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
// 设置可访问权限
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// 通过反射执行通知方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
此时就会来到com.wsh.aop.SimpleAspect#around()环绕通知方法的执行:
// 环绕通知
@Around("pointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws InterruptedException {
String methodName = proceedingJoinPoint.getSignature().getName();
System.out.println("执行" + methodName + "的环绕通知(@Around)...");
try {
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println(methodName + "()方法耗时: " + (endTime - startTime) + "毫秒");
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
}
当执行到proceedingJoinPoint.proceed()时,这时候又回到ReflectiveMethodInvocation#proceed()方法执行。
(五)、proceed()方法第五次进来: 当前拦截器索引为3,3 != 4,所以不会执行invokeJoinpoint(),然后将拦截器索引自增1,通过this.interceptorsAndDynamicMethodMatchers.get(4)获取到第五个拦截器:也就是MethodBeforeAdviceInterceptor拦截器,MethodBeforeAdviceInterceptor也是一个普通的拦截器,则触发拦截器链责任链的调用,执行MethodBeforeAdviceInterceptor.invoke()方法:
//
public Object invoke(MethodInvocation mi) throws Throwable {
// 执行前置通知方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 调用下一个拦截器的逻辑
return mi.proceed();
}
执行this.advice.before()方法时,就会来到com.wsh.aop.SimpleAspect#before(),执行前置通知的逻辑:
// 前置通知
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行" + methodName + "的前置通知(@Before)...");
}
前置通知执行完成后, 调用mi.proceed()会执行链中下一个拦截器的逻辑,这时候实际又回到ReflectiveMethodInvocation#proceed()方法执行。
(六)、proceed()方法第六次进来: 当前拦截器索引为4,4 = 4,所以会执行invokeJoinpoint()方法了。
// org.springframework.aop.framework.ReflectiveMethodInvocation#invokeJoinpoint
protected Object invokeJoinpoint() throws Throwable {
// 通过反射执行目标方法
// target:被代理的对象实例
// method:执行的方法
// arguments:方法参数
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
当执行 AopUtils.invokeJoinpointUsingReflection的时候,就会来到我们的目标方法的执行了:
public void addUser() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("新增用户...");
}
当目标方法执行完成后,就会执行com.wsh.aop.SimpleAspect#around()后置通知:proceedingJoinPoint.proceed()后面的逻辑了。
Around环绕通知处理完成后, 就来到:AspectJAfterAdvice#invoke()方法处理@After通知方法了:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 调用下一个拦截器的逻辑
return mi.proceed();
} finally {
// 不管方法正常退出还是异常退出,都会调用@After通知方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
可以看到,不管方法正常退出还是异常退出,都会调用@After通知方法。
invokeAdviceMethod()方法就会来到:com.wsh.aop.SimpleAspect#after
// 后置通知
@After("pointcut()")
public void after(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行" + methodName + "的后置通知(@After)...");
}
@After后置返回通知执行完成后,就会来到AfterReturningAdviceInterceptor#invoke()方法:
// org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
// 这里没有try-catch,如果方法是异常退出的话,则不会调用@AfterReturning通知方法
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
// org.springframework.aop.aspectj.AspectJAfterReturningAdvice#afterReturning
public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
}
}
接着就执行com.wsh.aop.SimpleAspect#afterReturning返回通知的逻辑:
// 返回通知
@AfterReturning("pointcut()")
public void afterReturning(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("执行" + methodName + "的后置返回通知(@AfterReturning)...");
}
至此,一次完整的AOP执行流程就算执行完了,我们对照前面的分析以及控制台的输出结果:
执行addUser的环绕通知(@Around)...
执行addUser的前置通知(@Before)...
新增用户...
addUser()方法耗时: 96730毫秒
执行addUser的后置通知(@After)...
执行addUser的后置返回通知(@AfterReturning)...
可以看到,输出的执行顺序与我们分析的顺序是一致的,Spring使用责任链模式依次处理拦截器链上所有的通知方法,前一个拦截器需要等后面的拦截器执行完成后才能执行。
三、总结
下面我们通过一张图说明拦截器链的整体执行流程:
至此,Spring AOP相关内容就介绍完毕了,从AOP相关术语、@EnableAspectJAutoProxy注解解析、增强器的获取、创建对象流程、AOP通知方法的执行流程等方面,详细总结了AOP知识。
最后,总结一下AOP的核心流程:
1)、通过@EnableAspectJAutoProxy注解开启AOP功能;
2)、解析@EnableAspectJAutoProxy注解,并注册AnnotationAwareAspectJAutoProxyCreator组件,AOP的准备和代理创建都在这个组件中完成;
3)、AnnotationAwareAspectJAutoProxyCreator继承AbstractAuto ProxyCreator实现了InstantiationAwareBeanPostProcessor接口,在方法postProcessBeforeInstantiation()中找到Spring容器中所有的增强器,为创建代理做准备;
4)、当我们的 bean 初始化完毕后,会触发所有 BeanPostProcessor 的 postProcessAfterInitialization()方法,AnnotationAwareAspectJAutoProxyCreator继承了AbstractAutoProxyCreator实现了BeanPostProcessor接口,此时就会调用我们的 AnnotationAwareAspectJAutoProxyCreator 的 postProcessAfterInitialization()方法,在方法postProcessAfterInitialization()中通过前面找到的候选增强器中找到合适的增强器来创建代理对象;
5)、当调用到被 AOP 代理的方法时,会走到对应的代理方法:JdkDynamicAopProxy#invoke 或 DynamicAdvisedInterceptor#intercept,该方法会创建 ReflectiveMethodInvocation,通过责任链的方式来执行所有的增强器和被代理的方法;