advice 在执行行 不管是 Jdk 的 代理 还是 CGlib 的代理 ReflectiveMethodInvocation 的 proceed()方法去实现的,具体可以去都之前的本专栏的 前几篇 aop 文章,里面有 Aop 实现的整个流程
@Aspect
@Component
public class TestAop {
@Before("pointCut()")
public void before(JoinPoint joinPoint)
{
Class clz = joinPoint.getTarget().getClass();
Signature signature = joinPoint.getSignature();
String name = signature.getName();
System.out.println("========="+"前置通知:"+name+"===========");
}
@After("zclvct.spring.aop.TestAop.pointCut()")
public void after(JoinPoint joinPoint)
{
Class clz = joinPoint.getTarget().getClass();
String name = clz.getName();
System.out.println("========="+"最终通知:"+name+"===========");
}
@Around("zclvct.spring.aop.TestAop.pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("========="+"环绕前"+"===========");
joinPoint.proceed();
System.out.println("========="+"环绕后"+"===========");
}
@AfterThrowing("zclvct.spring.aop.TestAop.pointCut()")
public void afterThrowing(JoinPoint joinPoint) throws Throwable {
System.out.println("========="+"异常通知"+"===========");
}
@AfterReturning("zclvct.spring.aop.TestAop.pointCut()")
public void afterReturning(JoinPoint joinPoint) throws Throwable {
System.out.println("========="+"后置通知"+"===========");
}
}
=========环绕前===========
=========前置通知:test===========
我是userserviceTest01
=========最终通知===========
=========后置通知===========
=========环绕后===========
他维护了 一个 ThreadLocal 对象 用于保存 MethodInvocation 的上下文,在后续的任何下调用链环节,只要需要用到当前的MethodInvocation就通过ExposeInvocationInterceptor.currentInvocation()静态方法获得。
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
// 设置 线程 MethodInvocation 副本
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
//递归执行 proceed 方法
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
第二个调用 AspectJAroundAdvice 的 invoke 方法 invoke 中调用 invokeAdviceMethodWithGivenArgs方法
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
//反射调用通知方法
//this.aspectInstanceFactory.getAspectInstance()获取的是切面的实例
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();
}
}
其实这个对象通过反射调用的方法其实是 我们之前调用的 TestAop 的 around 方法
ProceedingJoinPoint
@Around("zclvct.spring.aop.TestAop.pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("========="+"环绕前"+"===========");
joinPoint.proceed();
System.out.println("========="+"环绕后"+"===========");
}
此时 参数中的 joinPoint 是一个 MethodInvocationProceedingJoinPoint 实例
在 MethodInvocationProceedingJoinPoint 的 proceed 方法中可以看到
还是调用的 this.methodInvocation.invocableClone().proceed(); 方法继续递归
public Object proceed() throws Throwable {
return this.methodInvocation.invocableClone().proceed();
}
当然 此时 around 方法还没执行完成 只打印
=========环绕前===========
这里很简单 调用 在递归前 before 方法 回调 继续递归执行
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
这里很简单 调用 在递归前 before 方法 回调 继续递归执行
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
先递归调用 之后 finally 执行 最终通知
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
先递归 再调用
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
这里 利用 catch 捕获到 异常 在发生异常时执行 同时 将异常 抛出,防止异常被吃掉
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
// 我们从指数-1开始,并提前递增。 递归调用 所有拦截器链中的 Matcher 的 advice
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 运行目标对象的方法 也就是反射调用的指定目标
return invokeJoinpoint();
}
-* AspectJAfterThrowingAdvice 检查异常