`

比较分析 Spring AOP 和 AspectJ 之间的差别

 
阅读更多

 

面向方面的编程(AOP) 是一种编程范式,旨在通过允许横切关注点的分离,提高模块化。AOP提供方面来将跨越对象关注点模块化。虽然现在可以获得许多AOP框架,但在这里我们要区分的只有两个流行的框架:spring AOP和AspectJ。这里将会帮助你基于一些关键信息,为你的项目选择正确的技术

Spring AOP不同于大多数其他AOP框架。Spring AOP的目的并不是为了提供最完整的AOP实现(虽然Spring AOP具有相当的能力);而是为了要帮助解决企业应用中的常见问题,提一个AOP实现与Spring IOC之间的紧密集成。由于Spring AOP是容易实现的,如果你计划在Spring Beans之上将横切关注点模块化,Spring的这一目标将是要点之一。但同样的目标也可能成为一个限制,如果你用的是普通的Java对象而不是Spring beans,并基于此将横切关注点模块化的话另一方面AspectJ可用于基于普通Java对象的模块化在实施之前需要良好的关于这个主题的知识

在决定使用哪种框架实现你的项目之前,有几个要点可以帮助你做出合适的选择(同样适用于其他框架)。

Spring AOP致力于提供一种能够与Spring IoC紧密集成的面向方面框架的实现,以便于解决在开发企业级项目时面临的常见问题。明确你在应用横切关注点(cross-cutting concern)时(例如事物管理、日志或性能评估),需要处理的是Spring beans还是POJO。如果正在开发新的应用,则选择Spring AOP就没有什么阻力。但是如果你正在维护一个现有的应用(该应用并没有使用Spring框架),AspectJ就将是一个自然的选择了。为了详细说明这一点,假如你正在使用Spring AOP,当你想将日志功能作为一个通知(advice)加入到你的应用中,用于追踪程序流程,那么该通知(Advice)就只能应用在Spring beans的连接点(Joinpoint)之上。

例子:在appbeans.xml中配置如下的切入点(pointcut),那么当调用myServices bean的service方法时就将应用日志通知(advice)。

01 <!—Configuration snippet in appbeans.xml -->
02  
03   <bean id="myServices" class="com.ashutosh.MyServicesImpl " />
04  
05   <aop:config>
06  
07     <aop:aspect id="loggingAspect" ref="logging">
08  
09        <aop:around method="log" pointcut="execution(public * *(..))"/>
10  
11    </aop:aspect>
12  
13  </aop:config -->
14  
15 // Java file calling service method
16  
17 ApplicationContext beans =newClassPathXmlApplicationContext("appbeans.xml");
18  
19 MyServices myServices = (MyServices) beans.getBean("myServices");
20  
21 myServices.service(); // Logging advice applied here

看一下日志通知将要被应用处的注释,在这里应用程序将记录被调用方法的详细信息。但是,当你在service()方法中调用同一个类中的其他方法时,如果你没有使用代理对象,那么日志通知就不会被应用到这个方法调用上。

例如:

1 // MyServices service method
2  
3 public void service() {
4  
5   performOperation();// Logging advice not going to apply here
6  
7 }

如果你想要在通过this对象调用的方法上应用通知,那么你必须使用currentProxy对象,并调用其上的相应方法。

1 // MyServices service method
2  
3 public void service() {
4  
5   // Logging advice going to apply here
6  
7   ((MyServices) AopContext.currentProxy()).performOperation();
8  
9 }

于此相似,如果你想要在某对象的方法上应用通知,那么你必须使用与该对象相应的Spring bean。

1 public void service() {
2  
3   MyObject obj = new MyObject();
4  
5   Obj.performOperation();// Logging advice not going to apply here
6  
7 }

如果你想要应用该通知,那么上述代码必须修改为如下形式。

01 public void service() {
02  
03   MyObject obj = new MyObject();
04  
05  Obj.performOperation();// Logging advice not going to apply here
06  
07  ApplicationContext beans =newClassPathXmlApplicationContext("appbeans.xml");
08  
09  MyObject obj =(MyObject) beans.getBean("myObject");
10  
11  obj.performOperation()// Logging advice applied here
12  
13 }

于此不同,使用“AspectJ”你可以在任何Java对象上应用通知,而不需要在任何文件中创建或配置任何bean。

另一个需要考虑的因素是,你是希望在编译期间进行织入(weaving),还是编译后(post-compile)或是运行时(run-time)。Spring只支持运行时织入。如果你有多个团队分别开发多个使用Spring编写的模块(导致生成多个jar文件,例如每个模块一个jar文件),并且其中一个团队想要在整个项目中的所有Spring bean(例如,包括已经被其他团队打包了的jar文件)上应用日志通知(在这里日志只是用于加入横切关注点的举例),那么通过配置该团队自己的Spring配置文件就可以轻松做到这一点。之所以可以这样做,就是因为Spring使用的是运行时织入。

01 <!—Configuration -->
02  
03 <bean id="myServices" class="com.ashutosh.MyServicesImpl " />
04  
05  <aop:config>
06  
07   <aop:aspect id="loggingAspect" ref="logging">
08  
09       <aop:around method="log" pointcut="execution(public * *(..))"/>
10  
11   </aop:aspect>
12  
13 </aop:config -->

如果你使用AspectJ想要做到同样的事情,你也许就需要使用acj(AspectJ编译器)重新编译所有的代码并且进行重新打包。否则,你也可以选择使用AspectJ编译后(post-compile)或载入时(load-time)织入。

因为Spring基于代理模式(使用CGLIB),它有一个使用限制,即无法在使用final修饰的bean上应用横切关注点。因为代理需要对Java类进行继承,一旦使用了关键字final,这将是无法做到的。

例如,在Spring bean MyServicesImpl上使用关键字final,并配置一个execution(public * *(..))”这样的切入点,将导致运行时异常(exception),因为Spring不能为MyServicesImpl生成代理。

01 // Configuration file
02  
03 <bean id="myServices" class="com.ashutosh.MyServicesImpl" />
04  
05 //Java file
06  
07 public final classMyServicesImpl {
08  
09   ---
10  
11 }

在这种情况下,你也许会考虑使用AspectJ,其支持编译期织入且不需要生成代理。

于此相似,在static和final方法上应用横切关注点也是无法做到的。因为Spring基于代理模式。如果你在这些方法上配置通知,将导致运行时异常,因为static和final方法是不能被覆盖的。在这种情况下,你也会考虑使用AspectJ,因为其支持编译期织入且不需要生成代理。

你一定希望使用一种易于实现的方式。因为Spring AOP支持注解,在使用@Aspect注解创建和配置方面时将更加方便。而使用AspectJ,你就需要通过.aj文件来创建方面,并且需要使用ajc(Aspect编译器)来编译代码。所以如果你确定之前提到的限制不会成为你的项目的障碍时,使用Spring AOP。

使用AspectJ的一个间接局限是,因为AspectJ通知可以应用于POJO之上,它有可能将通知应用于一个已配置的通知之上。对于一个你没有注意到这方面问题的大范围应用的通知,这有可能导致一个无限循环。

例如,创建一个包含如下切入点的方面。

1 public aspectLogging {
2  
3   Object around() : execution(public * * (..))
4  
5   Sysytem.out.println(thisJoinPoint.getSignature());
6  
7   return proceed();
8  
9 }

在这种情况下,当proceed即将被调用时,日志通知会被再次应用,这样就导致了嵌套循环。

所以,如果你希望在Spring bean上采取比较简单的方式应用横切关注点时,并且这些bean没有被标以final修饰符,同时相似的方法也没有标以static或final修饰符时,就使用Spring AOP吧。相比之下,如果你需要在所提到的限制之上应用横切关注点,或者要在POJO上应用关注点,那么就使用AspectJ。你也可能选择同时使用两种方法,因为Spring支持这样。

参考链接:http://docs.spring.io/spring/docs/3.0.x/reference/aop.html

分享到:
评论

相关推荐

    Spring AOP的AspectJ支持jar包

    Spring AOP的AspectJ支持jar包; 包括: com.springsource.net.sf.cglib-2.2.0.jar com.srpingsource.org.aopalliance-1.0.0.jar com.srpingsource.org.aspectj.weaver-1.68.RELEASE.jar

    Spring AOP + AspectJ annotation example

    本篇将深入探讨如何结合Spring AOP和AspectJ注解进行实践。 首先,我们需要理解AOP的基本概念。面向切面编程是一种编程范式,它允许程序员定义“切面”,这些切面封装了跨越多个对象的行为或关注点。在Spring中,切...

    SpringAOP+AspectJ

    Spring AOP和AspectJ提供了强大的工具来管理横切关注点,使我们的代码更加模块化和易于维护。在实际项目中,可以根据需求选择适合的AOP实现方式,以实现更高效、更优雅的代码结构。通过深入理解AOP原理和实践,我们...

    Spring AOP @AspectJ 入门实例

    在IT行业中,Spring框架是Java企业级应用开发的首选,而Spring AOP(面向切面编程)则是其核心特性之...同时,阅读博客文章(链接已给出)会提供更详细的解释和示例,帮助你更好地掌握Spring AOP和@AspectJ的实际应用。

    Spring AOP + AspectJ in XML 配置示例

    这篇博客“Spring AOP + AspectJ in XML配置示例”旨在指导开发者如何在XML配置中实现Spring AOP和AspectJ的结合。 首先,我们需要理解AOP的基本概念。AOP通过将关注点(如日志、事务管理)与业务逻辑分离,提高了...

    Spring AOP 概念理解及@AspectJ支持

    **Spring AOP 概念理解** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的一个重要组成部分,它允许我们通过...理解和熟练运用Spring AOP及其@AspectJ注解是每个Spring开发者必备的技能之一。

    征服Spring AOP—— @AspectJ

    在压缩包文件"spring-aop-aspectj"中,可能包含了关于Spring AOP和@AspectJ的示例代码或文档,可以帮助你进一步理解和实践这些知识。通过学习和实践,你将能更好地掌握这一强大的工具,从而在你的IT职业生涯中征服...

    jar包---Spring Aop AspectJ新增包.rar

    总的来说,"jar包---Spring Aop AspectJ新增包.rar"提供的库文件可以帮助开发者在项目中实现Spring AOP和AspectJ的功能,从而更方便地进行面向切面的编程,提升代码的可维护性和模块化程度。同时,结合MyBatis这样的...

    @AspectJ配置Spring AOP,demo

    `springAOP2`可能是一个包含具体示例代码的目录。`基于@AspectJ配置Spring AOP之一 - 飞扬部落编程仓库-专注编程,网站,专业技术.htm`和其关联的`_files`目录可能包含了一个详细的教程或演示如何配置和运行@AspectJ的...

    spring AOP 实例(@AspectJ)

    一个基于@AspectJ的spring2.0 AOP应用实例,很小很简单,没有任何额外信息,最适合AOP入门学习。使用log4j打印信息。把项目直接import进myeclipse就可以使用啦......

    Spring AOP之基于AspectJ注解总结与案例

    通过阅读和理解这些代码,你可以更深入地掌握Spring AOP与AspectJ注解的使用。 总的来说,Spring AOP结合AspectJ注解使得我们能以声明式的方式处理横切关注点,提高代码的可读性和可维护性。通过实践和调试,你将更...

    spring-aop-aspectj(Schema)-case

    标题 "spring-aop-aspectj(Schema)-case" 指涉的是Spring AOP(面向切面编程)中使用AspectJ的Schema配置...同时,掌握源码分析能力也有助于深入理解Spring AOP和AspectJ的工作原理,为故障排查和性能优化提供基础。

    aspectj的jar spring使用aop需要的jar

    综上所述,为了在Spring中利用AspectJ的全部功能,你需要将对应的AspectJ JAR文件加入到项目类路径中,然后按照Spring文档或AspectJ文档的指导配置和使用AOP。这将使你的代码更加模块化,降低耦合,提高可维护性。

    spring-aop-aspectj-case

    在Spring框架中,AOP用于处理系统中的横切关注点,如日志、事务管理等,而AspectJ则是一个强大的、独立的面向切面编程语言,可以更灵活地定义切面和通知。 描述中提到的博文链接虽然没有具体内容,但通常博主会分享...

    Spring Aop之AspectJ注解配置实现日志管理的方法

    Spring Aop之AspectJ注解配置实现日志管理的方法 Spring Aop是基于AspectJ实现的面向切面编程(AOP),它提供了一个灵活的方式来实现日志管理。通过使用AspectJ注解,可以轻松地实现日志记录、性能监控、安全检查...

    spring和aspectj的aop实验

    标题"spring和aspectj的aop实验"表明我们将探讨如何在Spring中使用AspectJ进行AOP实践。这通常涉及到创建切面、定义通知、配置织入策略以及测试其效果。 1. **什么是AOP** AOP的核心概念是切面(Aspect),它封装...

    Spring的AOP依赖包-AspectJ

    Spring的AOP(面向切面编程)是一种强大的编程模型,它允许程序员在不修改源代码的情况下,通过插入额外的...在Spring4.3.7版本中,AspectJ的集成进一步完善了Spring的AOP框架,为开发者提供了更丰富的工具和可能性。

    Spring2.5使用AOP需要的aspectJ

    总的来说,Spring 2.5与AspectJ的结合使用提供了强大的AOP功能,允许开发者更优雅地处理横切关注点,提高代码的可维护性和可读性。正确理解和使用这些知识点对于提升Spring应用程序的架构设计和性能至关重要。

    spring AspectJ aop学习

    当我们谈论"spring AspectJ aop学习"时,我们将深入探讨Spring AOP如何结合AspectJ来实现更灵活的模块化和解耦。 首先,让我们理解AOP的概念。面向切面编程(Aspect Oriented Programming)是一种编程范式,旨在将...

    Spring 使用AspectJ 实现 AOP

    通过这种方式,Spring结合AspectJ提供的AOP支持,使得我们可以编写更加模块化和可维护的代码,将关注点分离,提高代码的重用性和可读性。在实际开发中,这尤其适用于那些横切多个业务逻辑的功能,如事务管理、日志...

Global site tag (gtag.js) - Google Analytics