前置增强的实例
通过前置增强对服务生的服务用语进行强制规范
1.假设服务生只做两件事:
第一:欢迎顾客
第二:对顾客提供服务
package com.aop2.advice;
public interface Waiter {
void greetTo(String name);
void serveTo(String name);
}
2.训练不足的服务生的服务情况
package com.aop2.advice;
public class NaiveWaiter implements Waiter {
public void greetTo(String name) {
System.out.println("greet to "+name+" ...");
}
public void serveTo(String name) {
System.out.println("serving to "+name+" ...");
}
}
说明:
NaiveWaiter只是简单地向顾客打招呼,闷不作声地走到顾客跟前,直接提供服务。
3.下面,我们对NavieWaiter地服务行为进行规范,让他们在打招呼和提供服务之前,都必须先对顾客使用礼貌用语。
package com.aop2.advice;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class GreetingBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
String clientName = (String)args[0];
System.out.println("How are you ! Mr."+clientName+".");
}
}
4.强制在服务生队伍中应用这个规定
1)使用CGLib代理
package com.aop2.advice;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
//使用CGLib代理
public class AdviceMain {
public static void main(String[] args){
Waiter target = new NaiveWaiter();
BeforeAdvice advice = new GreetingBeforeAdvice();
//Spring提供的代理工厂
ProxyFactory pf = new ProxyFactory();
//设置代理目标
pf.setTarget(target);
//为代理目标添加增强
pf.addAdvice(advice);
//生成代理实例
Waiter proxy = (Waiter)pf.getProxy();
proxy.greetTo("小2");
proxy.serveTo("明国宾");
System.out.println("执行完成");
}
}
2)使用JDK代理
package com.aop2.advice;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
//使用JDK代理
public class AdviceMain2 {
public static void main(String[] args){
Waiter target = new NaiveWaiter();
BeforeAdvice advice = new GreetingBeforeAdvice();
//Spring提供的代理工厂
ProxyFactory pf = new ProxyFactory();
//对指定的接口进行代理
pf.setInterfaces(target.getClass().getInterfaces());
//因为JDK代理的性能不高,启用优化
pf.setOptimize(true);
//设置代理目标
pf.setTarget(target);
//为代理目标添加增强
pf.addAdvice(advice);
//生成代理实例
Waiter proxy = (Waiter)pf.getProxy();
proxy.greetTo("小2");
proxy.serveTo("明国宾");
System.out.println("执行完成");
}
}
3)使用Spring方式
Spring配置文件:
<bean id="greetingAdvice" class="com.aop2.advice.GreetingBeforeAdvice"/>
<bean id="target" class="com.aop2.advice.NaiveWaiter"/>
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.aop2.advice.Waiter"
p:interceptorNames="greetingAdvice"
p:target-ref="target">
</bean>
AdviceMain3:
package com.aop2.advice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
//使用Spring的配置文件
public class AdviceMain3 {
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");
Waiter waiter = (Waiter)ctx.getBean("waiter");
waiter.greetTo("小2");
waiter.serveTo("小2");
System.out.println("执行完成");
}
}
5.说明:
1)BeforeAdvice接口是前置增强地接口,方法前置增强的MethodBeforeAdvice接口是其子类,
before(Method method,Object[] args,Object obj) throws Throwable:method为目标类的方法;args为目标类的入参,obj为目标类的实例
2)使用org.springframework.aop.framework.ProxyFactory代理工厂将GreetingBeforeAdvice的增强织入目标类NaiveWaiter中
3)org.springframework.aop.framework.AopProxy接口,并提供了两个类型的实现类
Cglib2AopProxy使用CGLib代理技术创建代理
JdkDynamicAopProxy使用JDK代理技术创建代理
4)ProxyFactoryBean是FactoryBean接口的实现类,ProxyFactoryBean负责为其他Bean创建代理实例
常见的可配置属性
target:代理的目标对象
proxyInterfaces:代理所要实现的接口,可以是多个接口。该属性还有一个别名属性interface
interceptorNames:需要植入目标对象的Bean列表,采用Bean的名称指定
这些Bean必须是实现了org.aoplliance.intercept.MethodInterceptor或者org.framework.aop.Advisor,配置中顺序对应调用的顺序;
singleton:返回的代理是否是单实例。默认为单实例
optiomize:当设置为true,强制使用CGLib代理。对于singleton的代理,推荐使用CGLib
proxyTargetClass:是否对类进行代理(而不是对接口进行代理),设置为true,使用CGLib代理