1.前置增强
org.springframework.aop.BeforeAdvice代表前置增强,因为Spring只支持方法级的增强,所以MethodBeforeAdvice是目前可用的前置增强,表示在目标方法执行之前实施增强,而BeforeAdvice是为了将来版本扩张需要而定义的。
以一个服务员在服务前需要跟顾客打招呼来介绍
我们先来定义一个接口
public interface Waiter { void greetTo(String name); void serverTo(String name); }
实现这个接口的NaiveWaiter类
public class NaiveWaiter implements Waiter { @Override public void greetTo(String name) { System.out.println("greet ot "+name+"..."); } @Override public void serverTo(String name) { System.out.println("serving "+name+"..."); } }
实现增强类,需要实现MethodBeforeAdvice接口
public class GreetingBeforAdivce implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] objects, Object o) throws Throwable { String clientName = (String)objects[0]; System.out.println("How are you :"+clientName+"."); } }
可以在xml文件里配置ProxyFactory,也可以直接通过类来实现代理
在xml文件里配置ProxyFactoryBean
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="greetingAdvice" class="com.target.GreetingBeforAdivce"/> <bean id="target" class="com.target.NaiveWaiter"/> <bean id="proxyWaiter" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="greetingAdvice" p:proxyInterfaces="com.target.Waiter" p:target-ref="target" /> </beans>
target:代理的目标对象
proxyInterface:代理所要实现的接口,可以是多个接口。
interceptorNames:需要植入目标对象的Bean列表,采用Bean的名称指定。这些Bean必须实现了org.aopalliance.interceptor.MethodInterceptor或者 org.springframework.aop.Advisor的Bean,配置中的顺序对应调用的顺序。
target-ref:指定对那个Bean进行代理
用一个类来测试一下
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Waiter waiter = (Waiter) context.getBean("proxyWaiter"); waiter.greetTo("ironman"); } }
2.后置增强
后置增强需要实现AfterReturningAdvice接口
public class GreetingAfterAdvice implements AfterReturningAdvice { @Override public void afterReturning(Object o, Method method, Object[] objects, Object o2) throws Throwable { System.out.println("Please enjoy yourself "); } }
当然也需要在xml文件中配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="greetingAdvice" class="com.target.GreetingBeforAdivce"/> <bean id="target" class="com.target.NaiveWaiter"/> <bean id="after" class="com.after.GreetingAfterAdvice"/> <bean id="proxyWaiter" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="greetingAdvice,after" p:proxyInterfaces="com.target.Waiter" p:target-ref="target" /> </beans>
p:interceptorNames是String[]类型,它接受Bean的名称而非增强Bean的实例。这是因为,ProxyBeanFactory内部在生成代理类时,需要使用增强Bean的类,而非增强的Bean的实例,即重用增强的横切逻辑代码,所以说增强时类级别的。
3.环绕增强
环绕增强需要实现MethodInterceptor接口
public class GreetingInterceptro implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { Object[] args = methodInvocation.getArguments(); String clientName = (String) args[0]; System.out.println("how are you ! Mr:"+clientName); Object obj = methodInvocation.proceed(); System.out.println("Please enjoy yourself!"); return obj; } }
在xml文件里配置proxyFactoryBean跟前面的事一样的。