Spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别:1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知是不能决定的,他们只是在方法的调用前后执行通知而已,即目标方法肯定是要执行的。2)环绕通知可以控制返回对象,即你可以返回一个与目标对象完全不同的返回值,虽然这很危险,但是你却可以办到。而后置方法是无法办到的,因为他是在目标方法返回值后调用。
Spring 提供了Interceptor 接口来实现环绕通知。它只有一个invoke 方法,该方法接只接受MethodInvocation 参数。MethodInvocation 可以获得目标方法的参数,并可以通过proceed 方法调用原来的方法。代码如下:
1)环绕通知
Java代码
- public class Around implements MethodInterceptor
- {
- public Object invoke( MethodInvocation invocation)throws Throwable {
- System.out.println("Round.invoke()");
- System.out.println("Arguments:");
- Object[] args = invocation.getArguments();
- for(Object arg: args) {
- System.out.println(arg.getClass().getName() + ": " + arg);
- }
- System.out.println("Method name:" + invocation.getMethod().getName());
- //修改了目标方法返回值
- return invocation.proceed() + " in Round.invoke()";
- }
- }
2)目标对象
Java代码
- public class Target implements Advice
- {
- public String test(int i, String s, float f) {
- System.out.println("Target.test()");
- System.out.println("target: " + this);
- StringBuffer buf = new StringBuffer();
- buf.append( "i = " + i);
- buf.append( ", s = \"" + s + "\"");
- buf.append( ", f = " + f);
- return buf.toString();
- }
- }
3)接口定义
Java代码
- public interface Advice
- {
- String test(int i, String s, float f);
- }
4)配置文件
Xml代码
- <beans>
- <bean id="around" class="spring.Around"/>
-
-
- <bean id="aop" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces" value="spring.Advice" />
- <property name="interceptorNames">
- <list>
- <value>around</value>
- </list>
- </property>
- <property name="target">
- <bean class="spring.Target" />
- </property>
- </bean>
- </beans>