当前位置:  首页>> 技术小册>> Spring AOP 编程思想(上)

章节:XML配置三种After Advice

在Spring框架中,面向切面编程(AOP, Aspect-Oriented Programming)是一种强大的编程范式,它允许开发者将横切关注点(如日志、事务管理、安全等)从业务逻辑中分离出来,以增强代码的可维护性和模块化。Spring AOP提供了多种方式来实现切面,其中XML配置是早期Spring版本中广泛使用的一种。本章节将深入探讨如何在Spring中通过XML配置来实现三种常见的After Advice(后通知):After Returning Advice、After Throwing Advice和After (Finally) Advice。

一、引言

在Spring AOP中,Advice是切面的动作部分,它定义了切面“做什么”以及“何时做”。根据通知执行的时机,可以将Advice分为多种类型,其中After Advice是在连接点(JoinPoint,通常是方法执行)之后执行的通知。After Advice进一步细分为三种类型:

  1. After Returning Advice:在目标方法正常执行完成后执行。
  2. After Throwing Advice:在目标方法抛出异常退出时执行。
  3. After (Finally) Advice:无论目标方法是否抛出异常,都会在目标方法执行完毕后执行,类似于Java中的finally块。

二、After Returning Advice

After Returning Advice允许你在目标方法正常执行完成后执行一些操作,比如记录方法返回值、进行资源清理等。在XML配置中,你需要使用<aop:after-returning>元素来定义After Returning Advice。

示例配置

假设我们有一个服务类UserService,其中包含一个saveUser方法,我们想在这个方法执行成功后记录一些信息。

  1. <beans ...>
  2. <!-- 定义切面 -->
  3. <bean id="loggingAspect" class="com.example.LoggingAspect"/>
  4. <!-- 配置AOP自动代理 -->
  5. <aop:config>
  6. <!-- 定义切入点 -->
  7. <aop:pointcut id="userServiceMethods"
  8. expression="execution(* com.example.service.UserService.*(..))"/>
  9. <!-- 配置After Returning Advice -->
  10. <aop:after-returning method="afterReturningAdvice"
  11. pointcut-ref="userServiceMethods"
  12. returning="result"/>
  13. </aop:config>
  14. </beans>

在上面的配置中,LoggingAspect类必须包含一个afterReturningAdvice方法,该方法接受一个与returning属性指定的参数名相匹配的参数(本例中为result),用于接收目标方法的返回值。

切面类实现
  1. package com.example;
  2. import org.aspectj.lang.annotation.Aspect;
  3. import org.aspectj.lang.JoinPoint;
  4. import org.aspectj.lang.annotation.AfterReturning;
  5. // 注意:虽然示例中使用了@Aspect注解,但在XML配置中不需要该注解
  6. public class LoggingAspect {
  7. // 注意:在XML配置中,不需要@AfterReturning注解
  8. public void afterReturningAdvice(Object result) {
  9. System.out.println("方法执行成功,返回值为:" + result);
  10. }
  11. }

注意:在XML配置中,切面类的方法上不需要添加AOP注解,因为所有的配置都是通过XML来完成的。

三、After Throwing Advice

After Throwing Advice用于在目标方法抛出异常时执行特定的逻辑,如记录错误信息、回滚事务等。在XML中,通过<aop:after-throwing>元素来定义。

示例配置

继续上面的例子,我们想在saveUser方法抛出异常时记录错误信息。

  1. <beans ...>
  2. <!-- 之前的配置保持不变 -->
  3. <!-- 配置After Throwing Advice -->
  4. <aop:after-throwing method="afterThrowingAdvice"
  5. pointcut-ref="userServiceMethods"
  6. throwing="ex"/>
  7. </beans>

LoggingAspect类中,你需要添加一个afterThrowingAdvice方法,它接受一个与throwing属性指定的参数名相匹配的参数(本例中为ex),用于接收抛出的异常。

切面类实现
  1. public class LoggingAspect {
  2. // 注意:在XML配置中,不需要@AfterThrowing注解
  3. public void afterThrowingAdvice(Throwable ex) {
  4. System.out.println("方法执行时抛出异常:" + ex.getMessage());
  5. }
  6. }

四、After (Finally) Advice

After (Finally) Advice无论目标方法是否成功执行,都会在其之后执行。这类似于Java中的finally块,用于执行必要的清理工作。在Spring AOP中,这种类型的Advice通过<aop:after>元素来定义,但需要注意的是,<aop:after>本身并不直接对应传统意义上的“finally”块,因为它不会捕获异常。然而,由于它总是执行,因此可以用作类似finally的功能。

示例配置
  1. <beans ...>
  2. <!-- 之前的配置保持不变 -->
  3. <!-- 配置After Advice,作为类似Finally的功能 -->
  4. <aop:after method="afterAdvice" pointcut-ref="userServiceMethods"/>
  5. </beans>

LoggingAspect类中,添加afterAdvice方法,该方法不接受任何与返回值或异常相关的参数,因为它总是在目标方法执行完毕后执行。

切面类实现
  1. public class LoggingAspect {
  2. // 注意:在XML配置中,不需要特定注解
  3. public void afterAdvice() {
  4. System.out.println("方法执行完毕,执行清理工作");
  5. }
  6. }

五、总结

通过XML配置Spring AOP的三种After Advice,我们能够将横切关注点从业务逻辑中分离出来,提高了代码的模块化和可维护性。After Returning Advice允许我们在方法成功执行后进行操作,After Throwing Advice则在方法抛出异常时执行,而After (Finally) Advice则提供了一种类似finally块的执行时机,用于执行必要的清理工作。尽管XML配置方式在Spring的较新版本中逐渐被注解配置所取代,但理解其原理对于深入学习Spring AOP仍具有重要意义。随着Spring Boot等现代框架的兴起,注解配置因其简洁性而变得更加流行,但XML配置在复杂项目或需要高度定制化配置的场景中仍然有其独特的价值。