AOP

331 阅读5分钟

什么是AOP

AOP是面向切面编程,将公共逻辑(如:日志、事务管理等)封装成切面,跟业务代码分开,做到了解耦的效果。

AOP有哪些实现方式?

动态代理和静态代理

静态代理:在编译时就将代码写入字节码,称为编译时增强
动态代理:在代码运行的时候在内存中创建一个代理类,不会修改字节码,

静态代理:AspectJ
动态代理:Spring

Spring AOP 的实现原理

通过动态代理实现。
如果对Spring的某个bean做了切面的话,那么Spring实际创建的是这个bean的代理对象,而不是直接实例化原始的bean。这个代理对象会拦截对该bean的调用,并在适当的时候调用自定义的通知逻辑。

Spring的AOP实现主要依赖两种实现形式:

  • JDK动态代理
  • CGLIB动态代理

JDK动态代理和CGLIB动态代理有什么区别

JDK动态代理

如果目标对象至少实现了一种接口,那么默认会采用该代理方式。
JDK动态代理只能对实现了接口的对象代理,它通过反射机制生成目标对象的代理对象, 并拦截对接口方法的调用,从而实现目标方法的增强处理。

CGLIB代理

如果目标对象没有实现任何接口,那么将会采用该代理方式。
CGLIB动态代理通过生成目标类的子类(动态子类),并重写非final非private方法以插入通知代码。

思考:如果一个类没有实现接口并且被final修饰,是否无法被代理?

是的。此时可以考虑移除final修饰符或改为AspectJ静态代理,因为该代理方式可以处理final类和方法,因为他是写入字节码当中的。

Spring通知有哪些类型?

切面的工作被称为通知。通俗来说就是要通过Spring AOP框架来触发的代码段。

Spring AOP 支持多种类型的通知(Advice),这些通知允许你在不同的执行点插入横切逻辑。以下是 Spring AOP 中的主要通知类型:

  1. @Before 通知 (前置通知):

    • 在连接点(通常是方法执行)之前运行,但不会影响连接点的执行流程。无论目标方法是否抛出异常或正常返回,@Before 通知都会执行。
    • 示例:用于日志记录、权限检查等。
  2. @AfterReturning 通知 (返回通知):

    • 在连接点成功完成后运行,即目标方法正常返回后执行。你可以访问并处理目标方法的返回值。
    • 示例:用于结果缓存、性能监控等。
  3. @AfterThrowing 通知 (异常通知):

    • 当连接点抛出异常时运行。你可以捕获特定类型的异常,并执行相应的逻辑。
    • 示例:用于异常日志记录、事务回滚等。
  4. @After (finally) 通知 (后置通知):

    • 无论连接点是正常完成还是抛出异常,@After 通知都会执行。它类似于 Java 的 finally 块。
    • 示例:用于资源清理、关闭数据库连接等。
  5. @Around 通知 (环绕通知):

    • 这是最强大的通知类型,它可以在连接点前后都执行代码,并且可以控制是否继续执行连接点。@Around 通知还可以访问和修改参数及返回值。
    • 示例:用于实现复杂的环绕逻辑,如事务管理、自定义方法拦截等。

Spring AOP 相关术语总结

Spring AOP(面向切面编程)涉及多个术语,理解这些术语对于掌握 Spring AOP 的使用和原理非常重要。以下是与 Spring AOP 相关的一些关键术语:

  1. Aspect(切面)

    • 切面是模块化的特殊类,它包含了切入点(Pointcut)和通知(Advice)。一个切面定义了横切关注点(cross-cutting concern),如事务管理、日志记录等。
  2. Join Point(连接点)

    • 连接点是指程序执行过程中的一个点,例如方法调用、异常抛出或字段访问。在 Spring AOP 中,连接点总是表示为方法执行。Spring AOP 仅支持方法级别的连接点。
  3. Pointcut(切入点)

    • 切入点是一个表达式或模式,用于匹配特定的连接点。它决定了哪些连接点将被通知(Advice)所影响。可以通过正则表达式或其他方式来定义切入点。
  4. Advice(通知/增强处理)

    • 通知是在特定的连接点上执行的动作。根据通知执行的时间点,可以分为以下几种类型:
      • @Before:在方法执行之前运行。
      • @AfterReturning:在方法成功完成后运行。
      • @AfterThrowing:在方法抛出异常后运行。
      • @After (finally):无论方法是否完成,都会运行。
      • @Around:包围连接点,在方法调用前后都运行,并可以控制是否继续执行连接点。
  5. Introduction(引入)

    • 引入允许向现有的对象添加新的接口和属性。这使得目标对象可以在不修改其代码的情况下实现新的功能。
  6. Target Object(目标对象)

    • 目标对象是被一个或多个切面所通知的对象。它也是原始的业务逻辑对象,通常是由 Spring 容器管理的 bean。
  7. AOP Proxy(AOP 代理)

    • AOP 代理是由 AOP 框架创建的对象,用来实现代理功能。有两种类型的代理:JDK 动态代理和 CGLIB 代理。代理对象会拦截对目标对象方法的调用,并在适当的时候应用通知逻辑。
  8. Weaving(织入)

    • 织入是将切面与目标对象组合的过程。这个过程可以在编译时、类加载时或运行时进行。Spring AOP 使用的是运行时代理的方式进行织入。