文章

【若依】11、自定义注解 + AOP

在系统运行的时候,动态的向系统中添加代码的行为,就是面向切面编程 AOP。

  • 前置通知:在目标方法执行之前执行。
  • 后置通知:在目标方法执行之后执行。
  • 异常通知:当目标方法抛出异常的时候执行。
  • 返回通知:当目标方法有返回值的时候执行。
  • 环绕通知:集大成者,包含了上面的四种情况。

在实际项目中,更多的是通过自定义注解 + AOP解决各种项目问题:

  1. 事务处理。
  2. 多数据源切换:通过一个前置通知,在目标方法执行之前,切换系统的数据源,这样,当目标方法执行的时候,就能够获取到切换之后的数据源了。
  3. 接口限流处理:通过一个前置通知,在目标方法执行之前,统计目标方法在给定的时间窗内已经被调用了多少次了,如果超过流量限制,就禁止直行。
  4. 接口幂等性处理:通过一个前置通知,在目标方法执行之前,先去统计当前请求在给定的时间内是否已经执行过了,如果已经执行过了,那么本次就拒绝执行。
  5. 数据权限的处理:通过一个前置通知,在目标方法执行之前,添加 SQL 条件,这些条件最终会被添加到 SQL 语句中,进而实现数据过滤。
  6. 日志记录:通过一个返回通知或者异常通知,当目标方法执行出错的时候或者执行有返回值的时候,通过一个异步任务,将日志记录下来。
  7. JdbcTemplate…
  8. XXXTemplate…

    AOP 原理

    AOP 就是基于动态代理,但是动态代理有两种实现方式:

  9. 基于 JDK 的动态代理:要求被代理的对象要有接口。
  10. 基于 CGLIB 的动态代理:不需要被代理的对象有接口。

在 Spring 中:

  1. 如果被代理的对象有接口,那么默认就是用 JDK 动态代理。
  2. 如果被代理的对象没有接口,那么就使用 CGLIB 动态代理。

在 Spring Boot 中:

  1. 在 Spring Boot 2.0 之前(不含 2.0):
    1. 如果开发者没有配置spring.aop.proxy-target-class属性,默认会使用 JDK 动态代理。
    2. 如果spring.aop.proxy-target-class属性设置为 true,那么对于有接口的对象,也会使用 CGLIB 动态代理。
    3. 如果spring.aop.proxy-target-class属性为 false,对于有接口的属性,会使用 JDK 动态代理。
  2. 在 Spring Boot 2.0 之后(含 2.0):
    1. 默认情况下,就是使用 CGLIB 动态代理,无论被代理的对象是否有接口,都使用 CGLIB 动态代理。

总结:

  • Spring 中,有接口用 JDK 动态代理;没接口用 CGLIB 动态代理。
  • Spring Boot 中,2.0 之前,和 Spring 一样;2.0 之后,首选 CGLIB,如果想用 JDK 动态代理,需要开发者手动配置。
本文由作者按照 CC BY 4.0 进行授权