Spring AOP 之 环绕通知
在所有的通知类型中,环绕通知最为强大。因为它能完全控制方法的执行过程,所以可以把前一篇文章中所有通知动作都合并到一个单独的通知里。甚至可以控制是否以及何时继续执行原始方法。
在Spring AOP中,环绕通知必须实现MethodInterceptor接口。这个接口是AOP联盟为了保持不同AOP框架之间的兼容性而定义的。当编写环绕通知时,必须记住——如果要继续执行原始方法,那么就必须调用methodInvocation.proceed()。如果忘记执行这一步,那么原始方法将不会被调用。下面的环绕通知合并了前面所创建的前置、后置和异常通知。
package org.mahz.easyaop.calculator.aop;
import java.util.Arrays;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class LoggingAroundAdvice implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
String methodName = invocation.getMethod().getName();
printTitle(methodName);
System.out.println("The method " + methodName + "()begin with "
+ Arrays.toString(invocation.getArguments()));
try {
Object returnValue = invocation.proceed();
System.out.println("The Method " + methodName + "() ends with "
+ returnValue);
return returnValue;
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
throw e;
}
}
private void printTitle(String methodName) {
System.out.println("==========================================");
System.out.println("============ Test " + methodName
+ " Method =============");
System.out.println("==========================================");
}
}
环绕通知类型非常强大、非常灵活,你甚至可以改变原始的方法参数值以及最终的返回结果。但是因为很容易忘记执行原始的方法,所以在使用这种通知时必须非常小心。
因为这个通知结合了前面所有通知,所以只需要为代理指定这一个通知即可。
<bean id="arithmeticCalculator" class="org.mahz.easyaop.calculator.impl.ArithmeticCalculatorImpl" />
<bean id="unitCalculator" class="org.mahz.easyaop.calculator.impl.UnitCalculatorImpl" />
<!--
<bean id="logginBeforeAdvice" class="org.mahz.easyaop.calculator.aop.LoggingBeforeAdvice" />
<bean id="logginAfterAdvice" class="org.mahz.easyaop.calculator.aop.LoggingAfterAdvice" />
<bean id="logginThrowsAdvice" class="org.mahz.easyaop.calculator.aop.LoggingThrowsAdvice" />
-->
<bean id="logginAroundAdvice" class="org.mahz.easyaop.calculator.aop.LoggingAroundAdvice" />
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Calculator</value>
</list>
</property>
<property name="interceptorNames">
<list>
<!--
<value>logginBeforeAdvice</value>
<value>logginAfterAdvice</value>
<value>logginThrowsAdvice</value>
-->
<value>logginAroundAdvice</value>
</list>
</property>
</bean>
执行结果:
==========================================
============ Test add Method =============
==========================================
The method add()begin with [4.0, 0.0]
4.0 + 0.0 = 4.0
The Method add() ends with 4.0
==========================================
============ Test sub Method =============
==========================================
The method sub()begin with [4.0, 0.0]
4.0 - 0.0 = 4.0
The Method sub() ends with 4.0
==========================================
============ Test mul Method =============
==========================================
The method mul()begin with [4.0, 0.0]
4.0 * 0.0 = 0.0
The Method mul() ends with 0.0
==========================================
============ Test div Method =============
==========================================
The method div()begin with [4.0, 0.0]
Division by zero