环绕增强允许在目标类方法调用前后织入横切逻辑,它综合实现了前置,后置增强两者的功能.
代码已托管到Github—> https://github.com/yangshangwei/SpringMaster
下面是我们用环绕增强同时实现上面的我们的示例。步骤如下: 创建业务接口类:Waiter.java 创建业务实现类:NativeWaiter.java 创建业务增强类:GreetingInterceptor.java 创建配置文件:conf-advice.xml 创建增强测试类:MethodInterceptorTest.java
业务接口类
package com.xgj.aop.spring.advice.methodInterceptor;
public interface Waiter {
void greetTo(String name);
void serverTo(String name);
}
业务实现类
package com.xgj.aop.spring.advice.methodInterceptor;
public class NaiveWaiter implements Waiter {
@Override
public void greetTo(String name) {
System.out.println("greetTo " + name);
}
@Override
public void serverTo(String name) {
System.out.println("serverTo " + name);
}
}
业务增强类GreetingInterceptor.java
package com.xgj.aop.spring.advice.methodInterceptor;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class GreetingInterceptor implements MethodInterceptor {
/**
* 截取目标类方法的执行,并在前后添加横切逻辑
*
* @param invocation
* 封装了目标方法和入参数组以及目标方法所带的实例对象
* @return 代理对象
* @throws Throwable
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// 获取目标方法的入参
Object[] args = invocation.getArguments();
// 在目标方法执行前调用
String clientName = (String) args[0];
System.out.println("GreetingInterceptor:How are you!" + clientName);
// 利用反射机制来调用目标方法
Object object = invocation.proceed();
// 在目标方法执行后调用
System.out.println("GreetingInterceptor: please enjoy youself!");
return object;
}
}
Spring直接使用AOP联盟所定义的MethodInterceptor作为环绕增强的接口,该接口拥有唯一的接口方法
public Object invoke(MethodInvocation invocation) throws Throwable
MethodInvocation不但封装了目标方法及其入参数组,还封装了目标方法所在的实例对象。通过MethodInvocation的getArguments()方法可以获取到目标方法的入参数组,通过proceed()方法反射调用目标实例相应的方法。
通过在实现类中定义横切逻辑可以很容易的实现方法前后的增强。
接下来在配置文件中对其进行配置:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="target" class="com.xgj.aop.spring.advice.methodInterceptor.NaiveWaiter"/>
<bean id="greetingAroundAdvice" class="com.xgj.aop.spring.advice.methodInterceptor.GreetingInterceptor">bean>
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.xgj.aop.spring.advice.methodInterceptor.Waiter"
p:interceptorNames="greetingAroundAdvice"
p:target-ref="target"/>
beans>
编写单元测试
package com.xgj.aop.spring.advice.methodInterceptor;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MethodInterceptorTest {
@Test
public void test() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:com/xgj/aop/spring/advice/methodInterceptor/conf-advice.xml");
Waiter waiter = ctx.getBean("waiter", Waiter.class);
waiter.greetTo("Xiao");
waiter.serverTo("GongJiang");
}
}
运行结果
可见环绕增强起了作用。