AOP实现(二)——Spring 2.0中的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 Advice pointcut 属性用于指定 pointcut 表示式,上面的例子表示此 Advice 将应用于 com.savage.aop.MessageSender 接口中的任何方法; method 属性表示 Advice 上要调用的方法。
    
现在调用任何 MessageSender 接口上的方法之前都会执行 LogBeforeAdvice before 方法,例如:
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 的定义),不再列举。

    九、 Pointcut
    在 Spring 2.0 中,

你可能感兴趣的:(spring,AOP,xml,bean)