介绍一下 aspectj

AspectJ是一种基于Java编程语言的面向切面编程(AOP)的扩展框架。它为Java开发者提供了在源代码级别实现横切关注点的能力。AspectJ通过引入新的关键字和注释,使得在现有的Java代码中可以更容易地定义和应用横切关注点,从而分离关注点和核心业务逻辑。

AOP是一种编程范式,它允许开发者将横跨应用程序的功能(称为切面)从核心业务逻辑中分离出来。这些切面可以横切多个类和对象,实现在不同位置的代码中共享的功能,例如日志记录、安全性检查、事务管理等。通过使用AspectJ,可以使代码更模块化、可维护性更高,并且遵循”单一职责原则”。

AspectJ的一些主要特性包括:

  1. 切面定义:使用AspectJ,您可以在Java类中定义切面,这些切面包含了横切关注点的逻辑。切面通常使用特殊的注释和关键字来标识它们,例如@Aspect注释。

  2. 切入点表达式:AspectJ提供了强大的切入点表达式语言,允许您精确地选择要将切面逻辑应用的连接点(例如方法调用、字段访问等)。切入点表达式可以指定类、方法、包等。

  3. 通知(Advice):AspectJ支持几种类型的通知,包括前置通知(Before)、后置通知(After)、返回通知(AfterReturning)、异常通知(AfterThrowing)和环绕通知(Around)。每种通知类型都在切入点前后插入不同类型的逻辑。

  4. 引入(Introduction):AspectJ允许您引入新的接口和实现到现有的类中,以实现横切关注点的功能。这使得您可以为类添加新的方法和属性,而无需修改其源代码。

  5. 织入(Weaving):织入是将切面逻辑应用到目标代码中的过程。AspectJ支持两种织入方式:编译时织入和运行时织入。编译时织入在编译期间将切面逻辑嵌入目标类中,而运行时织入在应用程序加载时动态地将切面逻辑织入。

总体而言,AspectJ是一个强大的工具,使得在Java应用程序中实现面向切面编程变得更加容易和灵活。它为开发者提供了一种有效的方式来管理与业务逻辑无关的功能,提高了代码的可重用性和可维护性。

aspsect 和 spring aop 的关系,二者的对比差异

AspectJ和Spring AOP都是面向切面编程(AOP)的实现方式,但它们有不同的实现方式和使用场景。

下面是它们之间的关系和对比差异:

  1. 关系:
    • AspectJ是独立的AOP框架,它是Java语言的扩展,通过特定的关键字和注解在源代码级别实现AOP。
    • Spring AOP是Spring框架的一部分,它是建立在动态代理基础上的AOP框架。Spring AOP提供了一种在运行时通过代理对象实现AOP的机制。
  2. 实现方式:
    • AspectJ使用编译时织入(CTW)或者运行时织入(RTW)来将切面织入目标代码中。编译时织入需要使用AspectJ编译器,而运行时织入则可以通过AspectJ的字节码增强(bytecode weaving)或者Spring框架的加载时或运行时代理来实现。
    • Spring AOP基于动态代理机制,主要使用Java反射来生成代理对象,实现对目标对象的切面织入。
  3. 对象范围:
    • AspectJ可以横跨不同模块和应用程序织入切面,它更加强大和灵活,但需要对项目进行特定的配置和编译。
    • Spring AOP通常用于在Spring应用程序中实现AOP。它更加轻量级,易于配置和集成,但只能对Spring管理的Bean进行AOP操作。
  4. 功能:
    • AspectJ支持五种通知类型(前置通知、后置通知、返回通知、异常通知和环绕通知)以及引入功能,能够更细粒度地控制切面逻辑。
    • Spring AOP只支持方法级别的连接点和四种通知类型(前置通知、后置通知、返回通知和异常通知),在功能上比AspectJ略有限制。
  5. 配置和集成:
    • AspectJ需要特定的AspectJ编译器和额外的配置,以及在构建过程中织入切面代码,相对复杂一些。
    • Spring AOP无需额外的编译器,直接在运行时通过代理实现AOP,可以更容易地与Spring应用程序集成。

总体而言,AspectJ提供了更丰富和强大的AOP功能,适用于大型项目和复杂的AOP需求。

Spring AOP则更适合于轻量级应用,或者对AOP功能有较简单需求的Spring项目。

根据具体的项目需求和复杂性,选择适合的AOP实现方式是很重要的。

在Spring项目中,您可以根据需要选择使用AspectJ或者Spring AOP,或者两者结合使用。

如果你想由浅入深学习 aspectj,会提哪10个问题?为什么

学习AspectJ时,以下是十个逐渐深入的问题,涵盖了从概念到实践的不同方面,有助于建立对AspectJ的全面理解:

  1. 什么是面向切面编程(AOP)?为什么使用AOP?
    • 这个问题将帮助理解AOP的基本概念和它解决的问题,为学习AspectJ提供背景。
  2. AspectJ是什么?它与Java有什么不同?
    • 这个问题解释了AspectJ作为AOP的实现方式,以及它与传统Java编程的不同之处。
  3. AspectJ的基本概念是什么?比如切面(Aspect)、切入点(Pointcut)、通知(Advice)等。
    • 这将介绍AspectJ的核心概念,为后续问题建立基础。
  4. AspectJ如何与Java代码集成?有哪些常用的织入方式?
    • 探讨AspectJ如何与Java代码结合,介绍编译时织入和运行时织入的概念。
  5. AspectJ切入点表达式是什么?如何选择目标连接点?
    • 这个问题将解释AspectJ的切入点表达式语言,帮助选择要应用通知的目标连接点。
  6. AspectJ支持哪些类型的通知?它们的应用场景是什么?
    • 深入研究不同类型的通知(前置通知、后置通知、返回通知、异常通知和环绕通知),了解它们的用途和用法。
  7. AspectJ的引入(Introduction)是什么?如何在现有类中引入新的功能?
    • 了解AspectJ的引入特性,学习如何通过它在现有类中添加新的接口和实现。
  8. AspectJ的编译和配置过程是怎样的?
    • 这将介绍AspectJ项目的编译过程,以及如何配置AspectJ编译器和插件。
  9. AspectJ在实际项目中的应用案例是什么?
    • 研究一些实际应用场景,了解AspectJ如何解决实际问题,促进对其应用的理解。
  10. AspectJ与Spring AOP的区别是什么?如何在Spring项目中选择使用?
    • 对比AspectJ和Spring AOP,理解它们的异同,并根据具体需求选择适合的AOP实现方式。

通过逐渐深入地回答这些问题,您将能够全面地了解AspectJ的概念、特性和应用,为进一步学习和实践打下坚实基础。

1. 什么是面向切面编程(AOP)?为什么使用AOP?

面向切面编程(AOP)是一种编程范式,它允许开发者将横跨应用程序的功能(称为切面)从核心业务逻辑中分离出来,以提高代码的可维护性和可重用性。

在传统的面向对象编程(OOP)中,业务逻辑通常散布在多个类和方法中,例如日志记录、安全性检查、事务管理等功能。这导致了代码的耦合性增加,使得代码难以理解和维护。

AOP通过将这些横切关注点(cross-cutting concerns)从核心业务逻辑中分离出来,形成一个独立的模块,称为切面。

切面是一种横切关注点的模块化实现,它可以独立于核心业务逻辑而存在。这样,切面可以跨越多个类和对象,在需要时将功能注入到代码中,而不需要修改核心业务逻辑。

使用AOP的主要优势包括:

  1. 模块化和可维护性:AOP允许开发者将关注点独立出来,使代码更加模块化,易于维护和理解。

  2. 代码重用:通过将功能抽象为切面,可以在不同的地方重用相同的功能,避免了代码的复制和粘贴。

  3. 降低耦合性:AOP的主要目标是分离关注点,从而减少代码间的耦合,使得代码更加灵活和可扩展。

  4. 聚焦核心逻辑:将横切关注点与核心业务逻辑分离,使得核心逻辑更加清晰,易于维护和测试。

  5. 集中管理横切关注点:通过使用AOP,可以将横切关注点集中管理,使得代码更加结构化和易于管理。

在复杂的应用程序中,AOP能够显著提高代码的可读性和可维护性。

它适用于许多不同的场景,如日志记录、性能监测、异常处理、安全性检查、事务管理等。

使用AOP,开发者可以更加专注于核心业务逻辑,而不需要在各个地方重复实现这些横切关注点。

2. AspectJ是什么?它与Java有什么不同?

AspectJ是一个独立的面向切面编程(AOP)框架,它是在Java编程语言之上的扩展,为Java开发者提供了在源代码级别实现AOP的能力。

AspectJ引入了新的关键字和注解,使得在现有的Java代码中可以更容易地定义和应用横切关注点,从而实现切面编程。

与传统的Java编程相比,AspectJ在以下方面有一些不同之处:

  1. AOP支持:AspectJ是专门为AOP而设计的,它在Java的基础上扩展了AOP的功能。它允许开发者使用切面和切入点表达式等概念,将横切关注点从核心业务逻辑中分离出来,实现更灵活的代码组织方式。

  2. 新的关键字和注解:AspectJ引入了新的关键字和注解,如aspectpointcutbeforeafter等,用于定义切面和通知。这些关键字和注解在传统的Java编程中是不存在的。

  3. 切面定义:在传统Java编程中,横切关注点通常散布在不同的类和方法中,而AspectJ允许开发者将这些关注点集中在切面中,形成一个单独的模块。这使得代码更加模块化,易于维护。

  4. 切入点表达式:AspectJ提供了强大的切入点表达式语言,允许开发者精确地选择要将切面逻辑应用的连接点。这使得切面的应用更加精准和灵活。

  5. 编译和织入:AspectJ支持编译时织入(Compile-Time Weaving,CTW)和运行时织入(Run-Time Weaving,RTW)。编译时织入需要使用AspectJ编译器,而运行时织入可以通过AspectJ的字节码增强(bytecode weaving)或者其他AOP框架的代理机制实现。

总体而言,AspectJ是Java语言的一个扩展,为开发者提供了更丰富和灵活的AOP功能。

它使得在Java代码中实现面向切面编程变得更加容易和直观,从而提高了代码的可维护性和可读性。不过需要注意,AspectJ需要额外的配置和编译过程,相对于传统的Java编程会更复杂一些。

3. AspectJ的基本概念是什么?比如切面(Aspect)、切入点(Pointcut)、通知(Advice)等。

AspectJ的基本概念包括切面(Aspect)、切入点(Pointcut)、通知(Advice)、连接点(Joinpoint)和目标对象(Target Object)等,下面分别对它们进行解释:

  1. 切面(Aspect): 切面是面向切面编程的核心组件,它是横切关注点的模块化实现。切面定义了一组与特定横切关注点相关的通知和切入点表达式。

    通常,一个切面对应着一个或多个横切关注点。切面可以包含前置通知、后置通知、返回通知、异常通知和环绕通知等多种通知类型。

  2. 切入点(Pointcut): 切入点用于定义在哪些连接点(Joinpoint)上应用通知。连接点是程序执行过程中的特定时刻,例如方法调用、方法返回、异常抛出等。切入点表达式是一个描述连接点的表达式,它可以精确地选择要应用通知的连接点。

  3. 通知(Advice): 通知是切面中实际的行为逻辑,它定义了在连接点处要执行的操作。AspectJ支持五种通知类型:
    • 前置通知(Before):在连接点之前执行。
    • 后置通知(After):在连接点之后执行(不考虑方法是否抛出异常)。
    • 返回通知(AfterReturning):在方法成功返回后执行。
    • 异常通知(AfterThrowing):在方法抛出异常后执行。
    • 环绕通知(Around):在方法调用前后执行,并可以在方法调用前后自由地控制连接点的执行。
  4. 连接点(Joinpoint): 连接点是程序执行过程中的一个特定时刻,例如方法调用、方法返回、异常抛出等。在AspectJ中,切入点会选择特定的连接点。通知会在选择的连接点处执行相应的行为逻辑。

  5. 目标对象(Target Object): 目标对象是AOP的织入目标,它是横切关注点所影响的对象。通常,目标对象是指应用程序中的某个具体对象,而不是切面本身。

综上所述,AspectJ使用切面、切入点和通知等概念来实现面向切面编程。切面定义了横切关注点的行为,切入点选择连接点,通知定义了在连接点处执行的行为逻辑。

通过这些概念的组合,AspectJ使得在Java应用程序中实现AOP变得更加灵活和强大。

4. AspectJ如何与Java代码集成?有哪些常用的织入方式?

AspectJ可以与Java代码集成,以实现面向切面编程。它提供了几种常用的织入方式来将切面逻辑应用于目标Java代码中。这些织入方式包括编译时织入(Compile-Time Weaving,CTW)、加载时织入(Load-Time Weaving,LTW)和运行时织入(Run-Time Weaving,RTW):

  1. 编译时织入(Compile-Time Weaving,CTW): 编译时织入是AspectJ最常用的织入方式之一。在这种方式下,AspectJ编译器会在源代码编译的过程中将切面逻辑嵌入到目标Java类中。开发者需要使用特定的AspectJ编译器,它会读取AspectJ切面和目标Java代码,将切面逻辑织入到目标类中生成新的字节码文件。然后,应用程序可以使用增强后的字节码文件来运行。这种织入方式是静态的,因为它在编译时期完成,运行时不需要AspectJ的支持。

  2. 加载时织入(Load-Time Weaving,LTW): 加载时织入是一种动态的织入方式。在这种方式下,AspectJ的织入逻辑并不在编译期执行,而是在类加载期间进行。开发者需要使用特定的Java虚拟机参数,启用AspectJ的加载时织入支持。AspectJ会通过特殊的类加载器来加载目标类,并在加载过程中将切面逻辑织入目标类中。这种方式相对于编译时织入更加灵活,因为它无需修改源代码,而是在运行时通过类加载器来动态织入切面。

  3. 运行时织入(Run-Time Weaving,RTW): 运行时织入是一种更加动态和灵活的织入方式。它不需要使用特定的编译器或类加载器,而是在运行时通过代理机制来实现。AspectJ可以通过创建目标类的代理对象,在代理对象中织入切面逻辑,并在执行时将切面逻辑应用到目标对象上。运行时织入不需要对目标类进行任何修改,因此可以方便地应用于第三方库或已编译的类。

选择何种织入方式取决于具体的需求和项目情况。编译时织入通常用于静态织入,适用于项目的初期阶段,或者需要将AOP应用于整个应用程序的情况。

加载时织入和运行时织入则更加动态和灵活,适用于需要在运行时动态选择织入目标的场景,或者对代码无法修改的情况。

5. AspectJ切入点表达式是什么?如何选择目标连接点?

AspectJ切入点表达式是一种用于选择目标连接点(Joinpoint)的表达式语言。切入点表达式允许您精确地定义在哪些连接点上应用通知(Advice)。

在AOP中,连接点是程序执行过程中的特定时刻,例如方法调用、方法返回、异常抛出等。

切入点表达式为您提供了选择特定连接点的灵活方式,以便将切面逻辑应用于目标代码中。

AspectJ切入点表达式的语法非常灵活,它可以描述类、方法、包、访问修饰符等多种元素。

以下是一些切入点表达式的例子:

  1. 选择所有public方法:
    execution(public * *(..))
    
  2. 选择特定包下的所有方法:
    execution(* com.example.service.*.*(..))
    
  3. 选择特定类的所有方法:
    execution(* com.example.service.UserService.*(..))
    
  4. 选择返回类型为String的方法:
    execution(String com.example.service.*.*(..))
    
  5. 选择标注有自定义注解的方法:
    @annotation(com.example.annotations.Loggable)
    
  6. 选择在Service接口上定义的所有方法调用:
    call(* com.example.service.Service+.*(..))
    
  7. 选择特定方法上的所有异常抛出:
    handler(Exception) && within(com.example.service.*)
    

上述例子只是一小部分切入点表达式的示例,实际上,AspectJ切入点表达式非常强大,可以描述非常复杂的连接点选择规则。

在选择切入点时,您可以根据目标代码的结构和需求来设计切入点表达式。确保切入点表达式足够准确,避免不必要的织入操作。

要选择目标连接点,您需要考虑以下几个方面:

  1. 目标方法的签名:根据目标方法的名称、参数类型和返回类型来选择连接点。

  2. 访问修饰符:根据目标方法的访问修饰符(public、private、protected等)来选择连接点。

  3. 所在的包和类:根据目标方法所在的包和类名来选择连接点。

  4. 注解:根据目标方法上的特定注解来选择连接点。

  5. 继承关系:根据目标方法所在的类或接口的继承关系来选择连接点。

  6. 异常类型:根据目标方法可能抛出的异常类型来选择连接点。

确保切入点表达式选择的连接点精确地对应于您要应用切面逻辑的目标代码位置,以便实现精确的AOP操作。

6. AspectJ支持哪些类型的通知?它们的应用场景是什么?

AspectJ支持五种类型的通知(Advice),每种通知在AOP中有不同的应用场景。这些通知类型分别是:

  1. 前置通知(Before): 前置通知在目标方法执行之前执行,用于在目标方法调用之前插入额外的逻辑。前置通知常用于记录日志、权限检查、输入参数验证等操作。它可以在方法调用之前拦截并执行一些前期操作,例如在方法执行前记录方法名、参数等信息。

  2. 后置通知(After): 后置通知在目标方法执行之后执行,无论目标方法是否抛出异常。后置通知通常用于清理资源、记录方法执行的状态信息等操作。由于后置通知无法访问目标方法的返回值或抛出的异常,因此主要用于收尾工作。

  3. 返回通知(AfterReturning): 返回通知在目标方法成功执行并返回结果后执行。它可以访问目标方法的返回值,并根据返回值做出相应处理。返回通知常用于执行某些后续操作,例如根据方法返回值进行判断、记录返回结果等。

  4. 异常通知(AfterThrowing): 异常通知在目标方法抛出异常后执行。它用于处理目标方法抛出的异常,并根据异常类型做出相应的处理。异常通知常用于异常处理、错误日志记录等操作。

  5. 环绕通知(Around): 环绕通知是最强大和最灵活的通知类型。它可以完全控制目标方法的执行过程,包括在方法之前、之后或者根本不执行方法。环绕通知可以决定是否继续执行目标方法,也可以修改目标方法的输入参数和返回值。它通常用于需要在目标方法执行前后进行一系列处理的场景,例如性能监测、事务管理等。

应用场景举例:

  • 前置通知:在用户执行某个操作之前,进行权限检查,确保用户有相应的权限。
  • 后置通知:在文件处理完成后,进行资源清理,确保文件句柄等资源得到释放。
  • 返回通知:在方法执行完成后,根据返回结果进行日志记录,统计等操作。
  • 异常通知:在方法抛出异常时,记录异常信息,并进行错误处理。
  • 环绕通知:在方法执行前后进行性能监测,计算方法执行时间等。

通过选择不同的通知类型,AspectJ可以将切面逻辑插入到目标代码的不同执行时机,实现精细的横切关注点的控制。

因此,合理选择和组合通知类型是实现AOP的关键。

7. AspectJ的引入(Introduction)是什么?如何在现有类中引入新的功能?

AspectJ的引入(Introduction)是一种特殊的切面功能,它允许您在现有的类中引入新的功能,而无需修改类的源代码。

通过引入,您可以在不修改目标类的情况下,为类添加新的接口和实现,从而实现了横切关注点的功能。

在AspectJ中,引入通过在切面中定义特定的declare parents语句来实现。declare parents语句用于指定目标类应该实现的新接口,以及由切面提供新接口的实现。通过这种方式,AspectJ可以在运行时动态地为目标类添加新功能,而目标类本身并不知道这些新功能的存在。

下面是一个简单的示例,展示了如何在现有类中引入新的功能:

假设有一个Calculator类:

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

现在我们想要为Calculator类引入一个Logging接口,该接口具有一个log(String message)方法来记录日志。

我们可以使用AspectJ的引入功能来实现这个需求:

public interface Logging {
    void log(String message);
}

public aspect LoggingAspect {
    declare parents: Calculator implements Logging;
    
    public void Calculator.log(String message) {
        System.out.println("Logging: " + message);
    }
}

在上面的代码中,我们定义了一个名为Logging的新接口,并在LoggingAspect切面中使用declare parents语句将Calculator类与Logging接口关联。

这样,Calculator类就可以在运行时动态地拥有Logging接口的功能。在LoggingAspect切面中,我们还提供了Calculator.log()方法的实现,用于记录日志。

现在,Calculator类就具有了Logging接口的功能,可以在使用Calculator类的地方调用log()方法来记录日志,而无需修改Calculator类的源代码。

通过引入功能,AspectJ提供了一种非常强大和灵活的方式来扩展现有类的功能,而不需要修改类的源代码,从而实现了AOP的核心目标之一:分离关注点。

9. AspectJ在实际项目中的应用案例是什么?

AspectJ在实际项目中有许多应用案例,它可以用于解决各种横切关注点的问题,提高代码的可维护性和可重用性。

以下是一些AspectJ在实际项目中的常见应用案例:

  1. 日志记录: 使用AspectJ来自动记录方法的调用信息、参数值、返回值以及执行时间,从而实现统一的日志记录功能。这样可以避免在每个方法中都手动添加日志记录代码,简化日志处理流程。

  2. 事务管理: 使用AspectJ来实现声明式的事务管理,将事务的开启、提交、回滚等逻辑从业务代码中抽离出来。这样可以使得事务处理更加集中化和灵活。

  3. 安全性检查: 使用AspectJ来实现安全性检查,例如权限验证,对敏感数据的访问控制等。这样可以确保系统只有经过授权的用户才能执行特定的操作。

  4. 性能监测: 使用AspectJ来监测方法的执行时间和性能指标,从而进行性能分析和优化。这样可以帮助开发者找到应用程序中的性能瓶颈并进行改进。

  5. 异常处理: 使用AspectJ来处理异常,例如记录异常信息、发送告警通知等。这样可以帮助开发者及时发现并解决系统中的异常情况。

  6. 缓存管理: 使用AspectJ来实现缓存管理,例如将查询结果缓存起来,避免重复查询数据库。这样可以提高系统的响应速度和性能。

  7. 国际化(i18n)支持: 使用AspectJ来在运行时切入并转换文本资源的显示,从而实现国际化支持。这样可以方便地实现多语言的界面显示。

  8. 审计日志: 使用AspectJ来自动记录用户操作和数据变更等敏感操作,形成审计日志。这样可以保留系统操作记录,用于监控和追踪系统的使用情况。

  9. 异常转换: 使用AspectJ来捕获和转换异常,将低级异常转换为更高级别的异常,从而实现异常的层级化处理。

这些只是AspectJ在实际项目中应用的一部分案例,实际上,AspectJ可以应用于各种不同的横切关注点,解决项目中的各种需求。

它的强大功能和灵活性使得开发者可以更加便捷地实现各种AOP操作,并提高代码的质量和可维护性。

10. AspectJ与Spring AOP的区别是什么?如何在Spring项目中选择使用?

AspectJ和Spring AOP都是面向切面编程(AOP)的实现方式,它们在一些方面有一些区别。

下面是AspectJ和Spring AOP的主要区别:

  1. 实现方式
    • AspectJ是独立的AOP框架,它是在Java语言之上的扩展,提供了更强大和灵活的AOP功能。AspectJ可以通过编译时织入、加载时织入或运行时织入等方式来实现AOP。
    • Spring AOP是Spring框架中的AOP模块,它是对AspectJ的轻量级封装。Spring AOP主要使用动态代理机制,在运行时动态生成代理对象来实现AOP。
  2. 织入时机
    • AspectJ可以在编译期、类加载期或运行时对目标类进行织入,因此它支持静态织入和动态织入。
    • Spring AOP只能在目标类的运行时动态生成代理对象,并在代理对象中应用AOP逻辑。因此,它只支持运行时织入。
  3. 支持的切入点表达式
    • AspectJ支持更灵活和强大的切入点表达式语言,它可以对类、方法、访问修饰符等多种元素进行选择。
    • Spring AOP的切入点表达式相对简单,主要基于方法名称匹配,并且只能选择公共方法。
  4. 应用场景
    • AspectJ适用于复杂的AOP需求,例如对第三方库或已编译代码的AOP,以及更细粒度的切入点选择。
    • Spring AOP适用于对Spring容器管理的Bean应用AOP,例如在Spring Bean的方法上应用通知。它适用于大多数常规的AOP需求。

在选择在Spring项目中使用AspectJ还是Spring AOP时,可以考虑以下几个因素:

  1. 复杂性和灵活性
    • 如果项目需要更复杂和灵活的AOP功能,例如对第三方库进行AOP,或者更精确的切入点选择,可以选择AspectJ。
    • 如果项目只需要简单的AOP功能,并且希望与Spring框架无缝集成,可以选择Spring AOP。
  2. 对代码的侵入性
    • AspectJ需要对代码进行修改或使用特定的编译器/类加载器来实现AOP,因此它在一定程度上会侵入现有代码。
    • Spring AOP不需要对代码进行修改,它可以通过动态代理在运行时织入AOP,因此对现有代码的侵入性较低。
  3. 项目的技术栈
    • 如果项目已经使用了Spring框架,并且希望在Spring的IOC容器中管理AOP的Bean,可以选择Spring AOP。
    • 如果项目技术栈不限于Spring,并且希望在更广泛的范围内应用AOP,可以选择AspectJ。

综合考虑项目需求、复杂性、侵入性以及技术栈等因素,选择合适的AOP实现方式,可以更好地满足项目的实际需求。

有些项目可能会同时使用AspectJ和Spring AOP来满足不同的AOP需求。

参考资料

简易版的Spring框架之AOP简单实现(对我来说不简单啊)

spring-AOP(二)实现原理之AspectJ注解方式

Spring5参考指南:AspectJ注解

Spring AOP之@AspectJ注解

Spring AOP与AspectJ的对比及应用

https://programmer.ink/think/the-simplest-helloworld-example-of-aspectj.html

https://github.com/josephpconley/aspectj-java-quickstart