返回

Spring源码高级笔记之——Spring AOP应用之二

见解分享

第1节 AOP相关术语

1.1 业务主线

业务主线是指应用程序的业务逻辑,也就是应用程序的核心功能,比如一个电商系统的购物流程,或者一个银行系统的转账流程。业务主线代码往往是应用程序中最长的代码,也是最容易出错的代码。

1.2 横切逻辑

横切逻辑是指那些与业务逻辑无关的代码,但又需要在多个地方重复执行的代码,比如权限校验代码、日志代码、事务控制代码、性能监控代码。横切逻辑代码往往很短,但是却非常重要,因为它们可以帮助应用程序运行得更加安全、可靠和高效。

1.3 切点(JoinPoint)

切点是程序执行期间的特定点,可以在切点处插入增强代码。Spring AOP框架提供了多种方式来定义切点,比如可以通过注解、XML配置或者AspectJ表达式来定义切点。

1.4 通知(Advice)

通知是当切点被触发时执行的代码。Spring AOP框架提供了多种类型的通知,比如前置通知、后置通知、环绕通知、异常通知和最终通知。不同的通知会在不同的时间点执行,比如前置通知会在方法执行之前执行,后置通知会在方法执行之后执行,环绕通知会在方法执行前后执行,异常通知会在方法抛出异常时执行,最终通知无论方法是否抛出异常都会执行。

1.5 切面(Aspect)

切面是一个将切点和通知组合在一起的类。切面定义了横切逻辑,并指定了横切逻辑在何时何地执行。一个切面可以包含多个通知,每个通知都可以应用到不同的切点上。

1.6 织入(Weaving)

织入是指将切面的横切逻辑应用到业务主线代码的过程。织入可以在编译时、加载时或运行时进行。Spring AOP框架提供了两种织入方式:静态织入和动态织入。静态织入是在编译时将切面的横切逻辑织入到业务主线代码中,而动态织入是在加载时或运行时将切面的横切逻辑织入到业务主线代码中。

1.7 代理(Proxy)

代理是一种在不修改业务主线代码的情况下为业务主线代码提供横切逻辑的一种技术。Spring AOP框架提供了多种类型的代理,比如JDK动态代理、CGLIB代理和AspectJ代理。不同的代理技术有不同的优缺点,开发者可以根据自己的需要选择合适的代理技术。

第2节 Spring AOP的使用

2.1 配置Spring AOP

要使用Spring AOP,首先需要在Spring配置文件中配置Spring AOP框架。以下是一个示例:

<beans>
  <aop:aspectj-autoproxy proxy-target-class="true" />
</beans>

这个配置表示启用Spring AOP框架,并使用CGLIB代理技术。

2.2 创建切面

创建一个切面类,继承自AspectJ的org.aspectj.lang.annotation.Aspect注解。切面类中可以定义切点和通知。以下是一个示例:

@Aspect
public class LoggingAspect {

  @Pointcut("execution(* com.example.demo.*.*(..))")
  public void loggingPointcut() {
  }

  @Before("loggingPointcut()")
  public void beforeLogging(JoinPoint joinPoint) {
    System.out.println("Before method: " + joinPoint.getSignature().getName());
  }

  @After("loggingPointcut()")
  public void afterLogging(JoinPoint joinPoint) {
    System.out.println("After method: " + joinPoint.getSignature().getName());
  }

  @Around("loggingPointcut()")
  public Object aroundLogging(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("Around before method: " + joinPoint.getSignature().getName());
    Object result = joinPoint.proceed();
    System.out.println("Around after method: " + joinPoint.getSignature().getName());
    return result;
  }

  @AfterThrowing(pointcut = "loggingPointcut()", throwing = "e")
  public void afterThrowingLogging(JoinPoint joinPoint, Throwable e) {
    System.out.println("Exception in method: " + joinPoint.getSignature().getName() + ", exception: " + e.getMessage());
  }

  @AfterReturning(pointcut = "loggingPointcut()", returning = "result")
  public void afterReturningLogging(JoinPoint joinPoint, Object result) {
    System.out.println("Method: " + joinPoint.getSignature().getName() + ", result: " + result);
  }

}

这个切面类定义了5个通知:前置通知、后置通知、环绕通知、异常通知和最终通知。这些通知分别在方法执行之前、方法执行之后、方法执行前后、方法抛出异常时和方法无论是否抛出异常都会执行。

2.3 应用切面

将切面类应用到业务主线代码中。Spring AOP框架提供了多种方式来应用切面,比如可以通过注解、XML配置或者AspectJ表达式来应用切面。以下是一个示例:

@Aspect
@Component
public class LoggingAspect {

  @Pointcut("execution(* com.example.demo.*.*(..))")
  public void loggingPointcut() {
  }

  @Before("loggingPointcut()")
  public void beforeLogging(JoinPoint joinPoint) {
    System.out.println("Before method: " + joinPoint.getSignature().getName());
  }

  @After("loggingPointcut()")
  public void afterLogging(JoinPoint joinPoint) {
    System.out.println("After method: " + joinPoint.getSignature().getName());
  }

  @Around("loggingPointcut()")
  public Object aroundLogging(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("Around before method: " + joinPoint.getSignature().getName());
    Object result = joinPoint.proceed();
    System.out.println("Around after method: " + joinPoint.getSignature().getName());
    return result;
  }

  @AfterThrowing(pointcut = "loggingPointcut()", throwing = "e")
  public void afterThrowingLogging(JoinPoint joinPoint, Throwable e) {
    System.out.println("Exception in method: " + joinPoint.getSignature().getName() + ", exception: " + e.getMessage());
  }

  @AfterReturning(pointcut = "loggingPointcut()", returning = "result")
  public void afterReturningLogging(JoinPoint joinPoint, Object result) {
    System.out.println("Method: " + joinPoint.getSignature().getName() + ", result: " + result);
  }

}

这个切面类应用到了com.example.demo包下的所有类和方法上。

第3节 Spring AOP的优点

Spring AOP框架具有以下优点:

  • 代码复用: Spring AOP框架可以将横切逻辑与业务逻辑分离,从而实现代码复用。
  • 模块化开发: Spring AOP框架可以将应用程序划分为多个模块,每个模块负责不同的功能,从而实现模块化开发。
  • 增强: Spring AOP框架可以增强应用程序的功能,比如可以为应用程序添加权限校验、日志记录、事务控制和性能监控等功能。
  • 横切逻辑: Spring AOP框架可以将横切逻辑与业务逻辑分离,从而使应用程序更加清晰和易于维护。
  • 业务逻辑: Spring AOP框架可以将业务逻辑与横切逻辑分离,从而使应用程序更加灵活和可扩展。

第4节 Spring AOP的缺点

Spring AOP框架也存在一些缺点:

  • 性能开销: Spring AOP框架会带来一些性能开销,因为需要在程序执行期间动态织入横切逻辑。
  • 复杂性: Spring AOP框架的配置和使用相对复杂,需要开发者掌握一定的AOP知识。
  • 侵入性: Spring AOP框架需要对业务主线代码进行修改,这可能会导致应用程序的兼容性问题。

第5节 总结

Spring AOP框架是一个强大的工具,可以帮助开发者构建更灵活、更可扩展、更易于维护的应用程序。但是,Spring AOP框架也存在一些缺点,因此开发者在使用Spring AOP框架时需要权衡利弊。