Spring中AOP的实现 (二)

Spring 2.0 中,除了传统的通过实现 AOP AIP 的方式来实现 Advice 之外,还提供了两种更加简便的方式来实现 Advice 1 )基于 XML Schema 的设置; 2 )基于 Annotation 的支持,采用这两种方式, Advice 将不用实现特定的接口。现在让我们来看看如何使用这两种方式来分别实现 Before Advice After Advice Around Advice Throwing Advice
    
一、 Before Advice :基于 XML Schema
当基于 XML Schema 实现 Before Advice 时,你的 Advice 类不用实现 org.springframework.aop.MethodBeforeAdvice 接口,例如:
java 代码
 
  1. package com.savage.aop;  
  2.   
  3. import org.aspectj.lang.JoinPoint;  
  4.   
  5. public class LogBeforeAdvice {  
  6.     public void before(JoinPoint joinPoint) {  
  7.         System.out.println("Logging before " + joinPoint.getSignature().getName());  
  8.     }  
  9. }  


          before方法是在目标对象上的方法被执行前要执行的方法, before方法中的 JoinPoint参数是可选项,你可以根据需要决定是否需要 JoinPoint参数,通过 JoinPoint对象,你可以获得目标对象( getTarget())、目标方法上的参数( getArgs())等信息。
     然后在 XML中为目标对象指定 LogBeforeAdvice代理:
xml 代码
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.     http://www.springframework.org/schema/aop  
  8.     http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
  9.     <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
  10.       
  11.     <bean id="logBeforeAdvice" class="com.savage.aop.LogBeforeAdvice"></bean>  
  12.       
  13.     <aop:config>  
  14.         <aop:aspect id="logBefore" ref="logBeforeAdvice">  
  15.             <aop:before pointcut="execution(* com.savage.aop.MessageSender.*(..))" 
  16.                         method="before"/>  
  17.         </aop:aspect>  
  18.     </aop:config>  
  19. </beans>  


     如上所示,在 Spring 2.0中要使用基于 XML Sechma声明 AOP的方式,需要在 XML中加入 aop的名称空间。当基于 XML Sechma实现 AOP时,所有的 AOP都是在 <aop:config></aop:config>标签中声明的, <aop:aspect></aop:aspect>用于定义 Advice实例。 <aop:before></aop:before>表示当前实例用于实现 Before Advicepointcut属性用于指定 pointcut表示式,上面的例子表示此 Advice将应用于 com.savage.aop.MessageSender接口中的任何方法; method属性表示 Advice上要调用的方法。
     现在调用任何 MessageSender接口上的方法之前都会执行 LogBeforeAdvicebefore方法,例如:
java 代码
 
  1. package com.savage.aop;  
  2.   
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5.   
  6. public class AdviceDemo {  
  7.     public static void main(String[] args) {  
  8.         ApplicationContext context = 
  9.                            new ClassPathXmlApplicationContext("beans-config.xml");  
  10.         MessageSender sender = (MessageSender)context.getBean("messageSender");  
  11.         sender.sendMessage("message");  
  12.     }  
  13. }  

     二、 Before Advice:基于 Annotation
         
使用 Annotation来实现 Advice,在 XML文件上的定义要比基于 XML Sechema的方法要简便的多,但在实现 Before Advice类时,则需要使用到 @Aspect@Before标识,并需要引入 org.aspectj.lang.annotation包中的类。还以 LogBeforeAdvice为例, LogBeforeAdvice类需要改为:
java 代码
 
  1. package com.savage.aop;  
  2.   
  3. import org.aspectj.lang.JoinPoint;  
  4. import org.aspectj.lang.annotation.Aspect;  
  5. import org.aspectj.lang.annotation.Before;  
  6.   
  7. @Aspect  
  8. public class LogBeforeAdvice {  
  9.     @Before("execution(* com.savage.aop.MessageSender.*(..))")  
  10.     public void before(JoinPoint joinPoint) {  
  11.         System.out.println("Logging before " + joinPoint.getSignature().getName());  
  12.     }  
  13. }  


     如上所示,通过 @Aspect将一个类声明为 Aspect类,通过 @Before将方法声明 Before Advice,方法中的 JoinPoint同样是可选的。然后在 XML文件中做如下定义:
xml 代码
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.     http://www.springframework.org/schema/aop  
  8.     http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
  9.     <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
  10.       
  11.     <bean id="logBeforeAdvice" class="com.savage.aop.LogBeforeAdvice"></bean>  
  12.       
  13.     <aop:aspectj-autoproxy/>  
  14. </beans>  


     所有基于 Annotation实现的 Advice,在 XML文件中都只要使用 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>进行设置就可以了,非常简单。

     三、 After Advice:基于 XML Sechma
         
Before Advice一样,基于 XML Sechma实现 After Returning Advice时,不再需要 org.springframework.aop.AfterReturningAdvice接口:
java 代码
 
  1. package com.savage.aop;  
  2.   
  3. import org.aspectj.lang.JoinPoint;  
  4.   
  5. public class LogAfterReturningAdvice {  
  6.     public void afterReturning(JoinPoint joinPoint) {  
  7.         System.out.println("Logging after " + joinPoint.getSignature().getName());  
  8.     }  
  9. }  


然后在 XML中做如下设置:
xml 代码
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.     http://www.springframework.org/schema/aop  
  8.     http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
  9.     <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
  10.       
  11.     <bean id="logAfterReturningAdvice" 
  12.           class="com.savage.aop.LogAfterReturningAdvice"></bean>  
  13.       
  14.     <aop:config>  
  15.         <aop:aspect id="logAfterReturning" ref="logAfterReturningAdvice">  
  16.             <aop:after-returning   
  17.                 pointcut="execution(* com.savage.aop.MessageSender.*(..))"   
  18.                 method="logAfterReturning"/>  
  19.         </aop:aspect>  
  20.     </aop:config>  
  21. </beans>  


    四、 After Advice:基于 Annotation
        
Before Advice相似,使用 @AfterReturning来表示 After Returning Advice
java 代码
 
  1. package com.savage.aop;  
  2.   
  3. import org.aspectj.lang.JoinPoint;  
  4. import org.aspectj.lang.annotation.Aspect;  
  5. import org.aspectj.lang.annotation.AfterReturning;  
  6.   
  7. @Aspect  
  8. public class AfterReturningAdvice {  
  9.     @AfterReturning(pointcut="execution(* com.savage.aop.MessageSender.*(..))"
  10.                     returning="retVal")  
  11.     public void afterReturning(JoinPoint joinPoint, Object retVal) {  
  12.         System.out.println("Logging after " + joinPoint.getSignature().getName());  
  13.     }  
  14. }  


     这里和 Before Advice有点不同的是,在定义 Poincut表示式时,多了一个 returning属性,用于指定目标方法执行完后的返回值。
      XML文件中的设置与 LogBeforeAdvice的相似(将 logBeforeAdvice的定义改为 logAfterReturning的定义),不再列举。

     五、 Around Advice:基于 XML Sechma
          
Spring 2.0中, Around Advice不用实现 org.aoplliance.intercept.MethodInterceptor接口,但 Advice的方法必须返回对象,并且必须定义一个 ProceedingJoinPoint参数,例如:
java 代码
 
  1. package com.savage.aop;  
  2.   
  3. import org.aspectj.lang.ProceedingJoinPoint;  
  4.   
  5. public class LogAroundAdvice {  
  6.     public void invoke(ProceedingJoinPoint joinPoint) {  
  7.         System.out.println("Logging before " + joinPoint.getSignature().getName());  
  8.         Object retVal = joinPoint.proceed();  
  9.         System.out.println("Logging after " + joinPoint.getSignature().getName());  
  10.         return retVal;  
  11.     }  
  12. }  


XML中的设置如下:
xml 代码
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.     http://www.springframework.org/schema/aop  
  8.     http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
  9.     <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
  10.       
  11.     <bean id="logAroundAdvice" class="com.savage.aop.LogAroundAdvice"></bean>  
  12.       
  13.     <aop:config>  
  14.         <aop:aspect id="logAround" ref="logAroundAdvice">  
  15.             <aop:around   
  16.                 pointcut="execution(* com.savage.aop.MessageSender.*(..))"   
  17.                 method="invoke"/>  
  18.         </aop:aspect>  
  19.     </aop:config>  
  20. </beans>  


     六、 Around Advice:基于 Annotation
          
Before Advice相似,使用 @Around来表示 Around Advice
java 代码
 
  1. package com.savage.aop;  
  2.   
  3. import org.aspectj.lang.ProceedingJoinPoint;  
  4. import org.aspectj.lang.annotation.Aspect;  
  5. import org.aspectj.lang.annotation.Around;  
  6.   
  7. @Aspect  
  8. public class AfterReturningAdvice {  
  9.     @Around("execution(* com.savage.aop.MessageSender.*(..))")  
  10.     public void invoke(ProceedingJoinPoint joinPoint) {  
  11.         System.out.println("Logging before " + joinPoint.getSignature().getName());  
  12.         Object retVal = joinPoint.proceed();  
  13.         System.out.println("Logging after " + joinPoint.getSignature().getName());  
  14.         return retVal;  
  15.     }  
  16. }  


      XML文件中的设置与 LogBeforeAdvice的相似(将 logBeforeAdvice的定义改为 logAroundAdvice的定义),不再列举。

     七、 Throw Advice:基于 XML Sechma
         
Spring 2.0中, Throw Advice不用实现 org.springframework.aop.ThrowsAdvice接口,但 Advice的方法必须定义 Throwable(或其子类)参数,例如:
java 代码
 
  1. package com.savage.aop;  
  2.   
  3. import org.aspectj.lang.JoinPoint;  
  4.   
  5. public class LogThrowingAdvice {  
  6.     public void afterThrowing (JoinPoint joinPoint, Throwable throwable) {  
  7.         System.out.println("Logging when throwing " + joinPoint.getSignature().getName());  
  8.     }  
  9. }  


XML的设置如下:
xml 代码
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.     http://www.springframework.org/schema/aop  
  8.     http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
  9.     <bean id="messageSender" class="com.savage.aop.HttpMessageSender"></bean>  
  10.       
  11.     <bean id="logThrowingAdvice" class="com.savage.aop.LogThrowingAdvice"></bean>  
  12.       
  13.     <aop:config>  
  14.         <aop:aspect id="logThrowing" ref="logThrowingAdvice">  
  15.             <aop:after-throwing   
  16.                 pointcut="execution(* com.savage.aop.MessageSender.*(..))"  
  17.                 throwing="throwable"  
  18.                 method="afterThrowing"/>  
  19.         </aop:aspect>  
  20.     </aop:config>  
  21. </beans>  


     在 <aop:after-throwing></aop:after-throwing>中必须定义 throwing属性,指定方法中的 throwable参数。 Spring将根据异常类型决定是否调用 afterThrowing方法。

     八、 Throw Advice:基于 Annotation
java 代码
 
  1. package com.savage.aop;  
  2.   
  3. import org.aspectj.lang.JoinPoint;  
  4. import org.aspectj.lang.annotation.Aspect;  
  5. import org.aspectj.lang.annotation.AfterThrowing;  
  6.   
  7. @Aspect  
  8. public class AfterThrowingAdvice {  
  9.     @AfterThrowing(pointcut="execution(* com.savage.aop.MessageSender.*(..))"
  10.                    throwing="throwable")  
  11.     public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {  
  12.         System.out.println("Logging when throwing " 
  13.                            + joinPoint.getSignature().getName());  
  14.     }  
  15. }  


       XML文件中的设置与 LogBeforeAdvice的相似(将 logBeforeAdvice的定义改为 logThrowingAdvice的定义),不再列举。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值