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.*(..))" method="before"/>  
  16.         </aop:aspect>  
  17.     </aop:config>  
  18. </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 = new ClassPathXmlApplicationContext("beans-config.xml");  
  9.         MessageSender sender = (MessageSender)context.getBean("messageSender");  
  10.         sender.sendMessage("message");  
  11.     }  
  12. }  

    二、 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" class="com.savage.aop.LogAfterReturningAdvice"></bean>  
  12.       
  13.     <aop:config>  
  14.         <aop:aspect id="logAfterReturning" ref="logAfterReturningAdvice">  
  15.             <aop:after-returning   
  16.                 pointcut="execution(* com.savage.aop.MessageSender.*(..))"   
  17.                 method="logAfterReturning"/>  
  18.         </aop:aspect>  
  19.     </aop:config>  
  20. </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.*(..))", returning="retVal")  
  10.     public void afterReturning(JoinPoint joinPoint, Object retVal) {  
  11.         System.out.println("Logging after " + joinPoint.getSignature().getName());  
  12.     }  
  13. }  

    这里和 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.*(..))", throwing="throwable")  
  10.     public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {  
  11.         System.out.println("Logging when throwing " + joinPoint.getSignature().getName());  
  12.     }  

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