Spring AOP 和 AspectJ AOP 有什么区别?

时间:2023-03-26 09:58:36

什么是AOP

AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。

AOP技它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

实现AOP的技术,主要分为两大类:一是采用动态代理技术(典型代表为Spring AOP),利用截取消息的方式(典型代表为AspectJ-AOP),对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

相关概念

切面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。切面用spring的 Advisor或拦截器实现。 连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。 通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice 切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上 引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口(使用较少) 目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。 织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

AOP概念的通俗理解

1.通知(Advice): 通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。 2.连接点(Joinpoint): 程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。 3.切入点(Pointcut) :通知定义了切面要发生的“故事”和时间,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,Spring中允许我们方便的用正则表达式来指定 4.切面(Aspect) :通知和切入点共同组成了切面:时间、地点和要发生的“故事” 5.引入(Introduction) :引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能) 6.目标(Target) :即被通知的对象,如果没有AOP,那么它的逻辑将要交叉别的事务逻辑,有了AOP之后它可以只关注自己要做的事(AOP让他做爱做的事) 7.代理(proxy) :应用通知的对象,详细内容参见设计模式里面的代理模式 8.织入(Weaving) :把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机: ---- (1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器 ---- (2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码 ----(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术

Spring AOP 和 AspectJ AOP区别

Spring AOP 和 AspectJ AOP 都是 Java 平台上的 AOP 框架。AOP(面向切面编程)是一种编程思想,它可以将横切关注点(cross-cutting concerns)从程序主体逻辑中分离出来,使程序更加模块化、可重用和易于维护。

Spring AOP 和 AspectJ AOP 的主要区别在于它们的实现方式、性能和功能。

  • 首先,Spring AOP 是基于动态代理技术实现的,它可以在运行时动态地生成代理对象,从而实现 AOP。这种方式的优点是可以在不改变原有代码的情况下实现 AOP,但是它只能代理接口,而不能代理类,因此它的功能比 AspectJ AOP 有所限制。 相反,AspectJ AOP 是一个更加强大和灵活的 AOP 框架,它使用静态织入技术,在编译阶段将 AOP 代码织入到目标类中。这种方式可以代理类和接口,并且可以支持更加细粒度的切面,例如可以对类的具体方法进行切面。但是这种方式需要使用特定的编译器和工具,对项目的侵入性比较大。
  • 其次,Spring AOP 在性能上要比 AspectJ AOP 更高效,因为它使用的是动态代理技术,可以在运行时动态生成代理对象,而 AspectJ AOP 则需要在编译阶段将切面织入到目标类中,这样会增加一定的启动时间和内存开销。
  • 最后,AspectJ AOP 拥有更加丰富的切入点表达式,支持更加灵活的切面定义。同时它也提供了更多的通知类型,如前置通知、后置通知、环绕通知、抛出异常通知等,能够更加细粒度地控制 AOP 的逻辑。

Spring AOP 和 AspectJ AOP 都是优秀的 AOP 框架,但是它们的实现方式、性能和功能略有不同,开发者应根据自己的需求和实际情况来选择合适的框架。如果需要更加灵活、强大的 AOP 功能和更高的性能,可以选择 AspectJ AOP,如果只是简单的 AOP 功能,可以选择 Spring AOP。

一个框架根本不比另一个框架更好。 简而言之,选择很大程度上取决于我们的要求:

  • 框架:如果应用程序未使用Spring框架,那么我们别无选择,只能放弃使用Spring AOP的想法,因为它无法管理Spring容器无法达到的任何功能。但是,如果我们的应用程序是完全使用Spring框架创建的,那么我们可以使用Spring AOP,因为它易于学习和应用
  • 灵活性:鉴于有限的连接点支持,Spring AOP并不是完整的AOP解决方案,但它解决了程序员面临的最常见问题。尽管如果我们想更深入地挖掘和利用AOP的最大功能,并希望获得广泛的可用连接点的支持,那么AspectJ是一个不错的选择
  • 性能:如果我们使用的方面有限,则性能上将存在微不足道的差异。但是有时在应用程序具有成千上万个方面的情况下。在这种情况下,我们不想使用运行时编织,因此最好选择AspectJ。已知AspectJ比Spring AOP快8到35倍 两者兼有:这两个框架彼此完全兼容。我们总是可以尽可能利用Spring AOP,并且仍然使用AspectJ来获得前者不支持的连接点的支持。

示例:Spring AOP

示例:AspectJ AOP