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代理