2007-08-24

Spring AOP 学习笔记 - 几种Advice的建立

关键字: spring aop

Creating advice:

    advice object包含了所有需要添加到aspect的逻辑代码,因为Spring中的joinpoint model是基于method interception的,所以在spring中advice object是可以加载在method调用的范围内的。Spring支持以下集中比较基本的advice类型。

Advice types in spring
Advice type Interface Descritpion
Around org.aopalliance.intercept.MethodInterceptor Intercepts calls to the target
method
Before

org.springframework.aop.BeforeAdvice

org.springframework.aop.MethodBeforeAdvice

 

Called before the target
method is invoked
After org.springframework.aop.AfterReturningAdvice Called after the target
method returns
Throws org.springframework.aop.ThrowsAdvice Called when target
method throws an
exception

    以上的不同的advice类型保证了开发人员有机会在方法执行的前后和过程,甚至产生异常抛出的时候执行advice中的逻辑代码。下面是一个摘抄至Spring In action相关章节的例子。

    首先建立一个接口KwikEMart,Customer可以通过其中的buySquishee方法来购买Squishee。

java 代码

 

  1. public interface KwikEMart {   
  2. Squishee buySquishee(Customer customer) throws KwikEMartException;   
  3. }  

 

    同时我们完成一个类ApuEwikEMart来实现它。

java 代码

 

  1. public class ApuKwikEMart implements KwikEMart {   
  2. private boolean squisheeMachineEmpty;   
  3. public Squishee buySquishee(Customer customer)   
  4. throws KwikEMartException {   
  5. if (customer.isBroke()) {   
  6. throw new CustomerIsBrokeException();   
  7. }   
  8. if (squisheeMachineEmpty) {   
  9. throw new NoMoreSquisheesException();   
  10. }   
  11. return new Squishee();   
  12. }   
  13. }  

 

    这里定义了一些相关的异常。

    首先我们为buySquishee方法加上一个before advice。当Customer购买Squishee时,我们可以给他们一个温暖的问候。扩展org.springframework.aop.MethodBeforeAdvice接口。

java 代码

 

  1. public interface MethodBeforeAdvice {   
  2. void before(Method method, Object[] args, Object target)   
  3. throws Throwable   
  4. }  

 

    编写一个欢迎的advice object: WelcomeAdvice来实现MethodBeforeAdvice接口。

java 代码

 

  1. import java.lang.reflect.Method;   
  2. import org.springframework.aop.MethodBeforeAdvice;   
  3. public class WelcomeAdvice implements MethodBeforeAdvice {   
  4. public void before(Method method, Object[] args, Object target) {   
  5. Customer customer = (Customer) args[0];   
  6. System.out.println("Hello " + customer.getName() +   
  7. ". How are you doing?");   
  8. }   
  9. }  

 

    method参数表示当前被植入advice的方法,args包含了该方法所有的参数。下面就是把WelcomeAdvice和ApuKwikEMart连接起来。

xml 代码

 

  1. <beans>  
  2. <bean id="kwikEMartTarget"  
  3. class="com.springinaction.chapter03.store.ApuKwikEMart"/>  
  4. <bean id="welcomeAdvice"  
  5. class="com.springinaction.chapter03.store.WelcomeAdvice"/>  
  6. <bean id="kwikEMart"  
  7. class="org.springframework.aop.framework.ProxyFactoryBean">  
  8. <property name="proxyInterfaces">  
  9. <value>com.springinaction.chapter03.store.KwikEMartvalue>  
  10. property>  
  11. <property name="interceptorNames">  
  12. <list>  
  13. <value>welcomeAdvicevalue>  
  14. list>  
  15. property>  
  16. <property name="target">  
  17. <ref bean="kwikEMartTarget"/>  
  18. property>  
  19. bean>  
  20. beans>  

 

    org.springframework.aop.framework.ProxyFactoryBean是spring框架中很重要的一个类,它可以在不改变被代理类的前提下对其增加一些行为。这里对ApuKwikEMart做了代理,将一系列的interceptors加载在被代理类上,这里就是把welcomeAdvice加载到kwikEMartTarget上。

    当用户购买了squishee后,我们需要对用户表示感谢,这里就需要一个after advice来实现它。首先也是扩展org.springframework.aop.AfterReturningAdvice接口。

java 代码
  1. public interface AfterReturningAdvice {   
  2. void afterReturning(Object returnValue, Method method,   
  3. Object[] args, Object target) throws Throwable   
  4. }   
  5. }  

    然后编写ThankYouAdvice来实现它。

java 代码
  1. import java.lang.reflect.Method;   
  2. import org.springframework.aop.AfterReturningAdvice;   
  3. public class ThankYouAdvice implements AfterReturningAdvice {   
  4. public void afterReturning(Object returnValue, Method method,   
  5. Object[] arg2, Object target) throws Throwable {   
  6. System.out.println("Thank you. Come again!");   
  7. }   
  8. }  

    然后就是把ThankYouAdvice和ApuKwikEMart连接起来。其xml文件这里就不重复了。

    下面就到了Around Advice的一些简单使用说明,首先扩展org.aopalliance.intercept.MethodInterceptor接口。

java 代码
  1. public interface MethodInterceptor extends Interceptor {   
  2. Object invoke(MethodInvocation invocation) throws Throwable;   
  3. }  

    编写OnePerCustomerInterceptor来实现此接口。

java 代码
  1. import java.util.HashSet;   
  2. import java.util.Set;   
  3. import org.aopalliance.intercept.MethodInterceptor;   
  4. import org.aopalliance.intercept.MethodInvocation;   
  5. public class OnePerCustomerInterceptor implements MethodInterceptor {   
  6. private Set customers = new HashSet();   
  7. public Object invoke(MethodInvocation invocation)   
  8. throws Throwable {   
  9. Customer customer = (Customer) invocation.getArguments()[0];   
  10. if (customers.contains(customer)) {   
  11. throw new KwikEMartException("One per customer.");   
  12. }   
  13. Object squishee = invocation.proceed();   
  14. customers.add(customer);   
  15. return squishee;   
  16. }   
  17. }  

    这里需要注意的是invocation.proceed。执行invocation.proceed时就是对监视方法的执行,在此行前能访问到的信息都是方法执行前的,此后的就是方法执行后的。invocation.proceed方法返回的对象就是被监视方法的返回对象。

    当buySquishee方法执行产生异常时,我们同样可以使用Throws Advice来对其进行捕捉。查看org.springframework.aop.ThrowsAdvice接口。

java 代码
  1. void afterThrowing(Throwable throwable)   
  2. void afterThrowing(Method method, Object[] args, Object target,   
  3. Throwable throwable)  

    编写KwikEMartExceptionAdvice来实现以上其中一个方法。

java 代码
  1. import org.springframework.aop.ThrowsAdvice;   
  2. public class KwikEMartExceptionAdvice implements ThrowsAdvice {   
  3. public void afterThrowing(NoMoreSquisheesException e) {   
  4. orderMoreSquishees();   
  5. }   
  6. public void afterThrowing(CustomerIsBrokeException e) {   
  7. showCustomerAtmMachine();   
  8. }   
  9. }  

    这样当buySquishee方法抛出异常时,我们就可以根据异常类型的不同执行相应的方法。

评论
发表评论

您还没有登录,请登录后发表评论

cjyzpcl
搜索本博客
最近加入圈子
存档
最新评论