问题:
为什么spring的aop配置中的环绕通知需要在通知的方法加入一个ProceedingJoinPoint参数,并且为什么要调用getArgs()
和proceed(Object[] args)
方法呢?
陈述:
我们可以先来分析前置通知和后置通知,以及最终通知和异常通知。
前面说的这四种通知类型,都是能直接锁定通知在程序执行时执行的位置的。
为什么这么说呢?
比如前置通知,这个通知能够准确定位到它应该执行的位置,是因为它并不用关心我们通知本身的内容,他只要在对应的切入点表达式的位置前执行就可以了;
后置通知、最终通知和异常通知都是同理,这些通知并不用在一我们通知的本身内容是什么。
但是环绕通知就不一样了,使用环绕通知就会出现一个问题,它既然是环绕切入点表达式对应的方法执行,那么这个环绕的概念过于模糊,程序是一个很死板的东西,他并不知道我们所谓的环绕是个怎么样的环绕法,
举例说明:
这个切面是我自己定义的一个控制事务的类,已经在ioc容器中创建了对应的对象,id就是txManger
<aop:config>
<aop:aspect id="txAdvice" ref="txManger">
<aop:pointcut id="pt1" expression="execution(* *..*Service.*(..))"/>
<aop:around method="transactionAround" pointcut-ref="pt1"/>
</aop:aspect>
</aop:config>
那为什么说我们的环绕通知,必须使用ProceedingJoinPoint这个参数呢?
我们来看,下面的这个方法就是我们要实现的环绕通知。
/**
* 环绕通知
* @param joinPoint
* @return
*/
public Object transactionAround(ProceedingJoinPoint joinPoint) {
Object returnValue = null;
Object[] args = joinPoint.getArgs();
try {
beginTransaction();
returnValue = joinPoint.proceed(args);
commit();
} catch (Throwable throwable) {
rollback();
throwable.printStackTrace();
} finally {
release();
}
return returnValue;
}
}
如果我们不使用这个参数,这段方法是什么样的呢?
我们来写一下,如下
public void transactionAround() {
try {
beginTransaction();
commit();
} catch (Throwable throwable) {
rollback();
throwable.printStackTrace();
} finally {
release();
}
}
}
这时候我们大概有所眉目了,上面不使用ProceedingJoinPoint这个参数的环绕方法,很显然程序并不能识别出这个环绕是对切入点表达式对应的方法如何个环绕法(也就是在这个transactionAround方法执行完第一行,再执行切入点表达式对应的方法,还是执行完最后一行再执行切入点表达式。
所以这时候就需要用到这个参数了ProceedingJoinPoint
这个参数我们直接加到我们的环绕通知的这个方法的参数中即可,spring会帮我们自动注入。
ProceedingJoinPoint这个类的getArgs()
和proceed(Object[] args)
两个方法和我们动态代理中的Object[]arg
参数和method.invoke
方法很类似。getArgs是用来获取切入点表达式对应的方法所需的参数都是什么、proceed(Object[] args)
方法就是用来标识执行的切入点表达式对应的方法。
然后注意将方法执行后的返回值返回出去,所以我的transactionAround方法的返回值才是Object的。
别的也没什么了,一点拙见,仅供参考