刘旭斌,朱国宾,关培超,朱鑫伟
(1.武汉大学 国际软件学院,湖北 武汉 430079;2.武汉大学 测绘遥感信息工程国家重点实验室,湖北 武汉 430079)
在地理信息服务平台中,用户可浏览、发布以及使用各种地理服务,而管理员则需对用户行为进行审批管理。在Web服务进程中,为了进行错误追踪、分析用户行为,以便更好地提供服务,需对用户行为进行日志记录。
一个常规的Web 应用系统,一般会涉及系统业务相关的模块和分布在这些模块中的公共行为(如数据库事务处理、安全性、日志处理、权限控制、例外处理等)[1]。我们通常把前者称为核心关注点,后者因其“贯穿性”的特点称为横切关注点[1]。在地理信息服务平台中,OOP可以很方便地将其中的“名词”(如服务、用户等)映射为Java系统中的对象,这样更加贴近日常的思维方式,便于理解。即采用OOP处理核心关注点时,可以提高建模的效率。但由于横切关注点(如日志记录)几乎涉及到系统中的各个对象,如果采用OOP直接编码的方式,这些代码会分散在各个对象代码中,造成大量冗余,使得系统的核心业务逻辑模块与辅助模块耦合性较高。这样不仅会造成代码分散、混乱的问题,而且不便于后期维护和管理。此时OOP的传统优势不仅不能得到充分的发挥,反而成为影响代码简洁高效维护的障碍。而AOP则可以有效地解决这一问题。
AOP是对OOP技术的一种补充。OOP 把应用分解成带有层次结构的对象,而AOP把程序分解成为一些切面或关注点[2],它允许程序员对横切性的问题(Crosscutting Concerns——跨越典型职责界线的行为,例如事务处理、权限控制等)进行模块化[2],开发由原来的一维模式变为了二维模式,提高了应用系统开发维护的效率。AOP 就其本质而言,是用一种松散耦合的方式来实现独立的关注点,并组合这些关注点来实现最终系统[3],它很好地弥补了OOP和EJB的不足,可使地理信息服务平台的开发变得更加简洁高效易维护,代码重用性也得到了极大的提高。
AOP的概念是由施乐Palo Alto 研究中心的Gregor Kiczales于1977年提出的。由于OOP无法解决切面和业务核心逻辑模块形成横切,从而造成代码纠结问题。为此,研究者提出了一种新的AOP编程思想,解决了面向对象方法在非功能单元横向管理存在的缺陷,提供了一种明确捕获和模块化横切关注点(日志、事务、权限认证等)的机制[4],提高了系统的可扩展性,实现调用者和被调用者之间的充分解耦[5]。而切面、连接点、切入点、通知等机制是AOP的核心所在。切面是实现横切关注点的模块,连接点是切面将会被植入的点,切入点是一个或多个连接点的集合,通知则是在切入点将要执行的逻辑代码。
AOP的核心思想是将与系统核心业务逻辑无关的系统横切关注点(如数据库事务处理、安全性检查、日志记录等)抽取出来,单独对其进行建模、设计、实现,以提高系统程序的抽象性和模块化程度,改善软件的可复用性、可扩展性和可维护性。如图1所示,从遗留系统中分别抽取出核心业务逻辑模块和日志、事务等横切关注点,然后使用面向对象编程的思想实现业务逻辑方法,将模块化后的切面切入到业务逻辑方法前后,使其由原来的面向对象的一维空间实现,变成现在的二维空间实现。也就是说,原来的事务处理、日志等功能的实现被限制在每一个需要调用它的模块中,而现在这些模块只需专注实现自己的业务功能即可,从而避免了代码的分散和混乱,提高了代码的重用性。
自AOP提出以后,经过多年的深入研究,市场上已经出现了成熟度较高的AOP工具,如AspectJ、JBoss、Spring AOP等。但各种工具关注面不同,实现机制也有所区别,导致风格各异,适用场合也不同。本文将集中探讨AspectJ和Spring AOP的异同,并从多个角度比较它们的特征以及适用情况。
需要明确的是,不论哪一种工具,其设计目标都是将横切的切面问题模块化。因此,切入点就是AOP的核心。此外,AOP工具还提供了类型间声明和通知机制。3者的组合,构成了切面。不同AOP工具的主要区别在于切面声明的方式以及如何应用到系统中。
1) AspectJ的切面声明类似于Java语言中的类声明,是基于Java语言的语法及语义的扩展。它拥有属于自身的基于Java平台的AOP语法、AspectJ编译器以及启动器。
2)Spring AOP实现切面声明的方式包括基于XML方式、@AspectJ注解方式等。Spring AOP不需要独立的启动器,因为它依赖的是 Spring 框架方便的、最小化的运行配置。
AspectJ由Java语言扩展而来,属于代码级,在处理新建项目时可以考虑使用,而在处理遗留系统中则不太适合,因为可能会大量修改源代码。Spring AOP提供的XML风格切面声明在修改切入点时只需在XML配置文件中进行修改,更加简洁方便。表1详细对比了2种方式的特征。
表1 2种实现方式特征对比
和大多数Web项目一样,本文介绍的地理信息服务平台中的日志系统要求不是特别精细,只需使用轻量级的Spring AOP即可满足需求。而对于其他项目,若是遗留系统,需添加日志模块,则选择Spring AOP更加合适,它可以在不修改源代码的基础上将日志模块整合进去,而AspectJ则更适合用在粒度级要求更加精细的系统中。
本文介绍的地理信息服务平台旨在为用户提供一个发布共享各种地理服务的平台,用户也可申请使用其他用户共享的服务。在该平台中,普通用户的注册、服务发布及使用等申请,以及管理员审批动作,均需记录在日志系统中。但在开发中,日志输出分散在各个模块,且在许多源文件中相互纠结,使得系统的相关复杂度较高,不利于后期的改进及维护。因此,我们将采用AOP解决方案,以期降低相关复杂度,使系统变得简单可靠,便于维护。
此系统的业务逻辑是用户可通过平台浏览新闻、申请注册账号、申请发布服务、申请使用服务,管理员可通过平台发布新闻以及对用户申请进行审批,而日志系统负责记录下这些动作,前者的执行会引发后者的执行,并将数据等信息传递给后者,以便准确记录。
为了测试AOP方式解决方案的优势,设计了基于OOP的解决方案进行对比。
方案一:仅OOP实现,见图2。
方案二:OOP与AOP结合实现,见图3。
OOP+AOP实现图方案二在方案一的基础上,将代码中日志记录独立出来成为一个模块,通过AOP配置文件,实现自动拦截切点(原理见图4)和日志输出功能。
与方案一相比,方案二更易降低每个模块的复杂度,提高模块的可靠性,使得代码更为简单。如果我们把OOP看作从上到下的软件开发过程,那么AOP则是从左到右的软件开发过程[6],即从面向对象的一维思考方式转变成二维空间的实现[7]。
使用方案二方式实现地理信息服务平台时,其中的日志记录按紧急程度分为debug、info、warning、err、引用emerg 5个level级别,其中,debug为不包含函数条件或问题的其他信息;info为提供信息的消息 ;warning为预警信息;err为阻止工具或某些子系统部分功能实现的错误条件;引用emerg为该系统不可用。而本平台日志系统需记录的为一般消息(即用户和管理员的操作),所以选择使用info级别记录相应的日志。日志系统的逻辑架构如图5所示。
实现时,我们需要找到切面相应的连接点。在UserApproveDao.java类中,针对具体的用户注册申请、管理员审批及删除注册申请的动作,找到对应的方法addUserApprove( )、Approve( )、delUserApprove( ), 即为连接点JoinPoint。
通知Advice的实现是通过记录日志的方法log_AOP(JoinPoint joinPoint, Object returnValue)完成的。
Java代码(部分):
public void log_AOP(JoinPoint joinPoint, Object returnValue) {
if(join Point.get Signa ture().get Name().equals("addUserApprove")) {
String userId = (String) joinPoint.getArgs()[0];
syslog.info(logFormat.format(..);
}
//后续动作
}
最后,需要配置系统的配置文件applicationContext.xml。
Xml代码(部分):
pointcut-ref="pointCut_0" returning="returnValue" /> 在比较OOP和AOP两种方案时,采用相同的测试条件: 1)硬件配置:ubuntu服务器;苹果Mac(4 G内存,CPU 2.66 GHz双核); 2)软件支持平台:Windows7(64位), myeclipse 10.5, syslog-ng_3.3.1; 3)测试案例:2n(n=1,2,3,…,13)个线程同时向日志服务器写日志; 4)前提条件:网络稳定,局域网100 MB带宽; 5)预期结果:在线程数较少的情况下,2种方式的耗时相差不大。但随着线程数指数级递增,2种方式的耗时也逐渐增大,AOP方式的耗时会比传统编码方式的耗时长,且2者的差距越来越大。 测试结果如表2、表3所示。 表2 传统直接编码方式 表3 AOP方式 测试和对比(见图6)表明,在线程数较少时,两者的差别不大,甚至基于AOP的实现所耗时间系统性地低于基于OOP的实现方式。但随着线程数指数级的递增,AOP方式的耗时比传统编码方式的耗时长,且差距越来越大。但在实用情况下,如果考虑1 024个并发数量是合理的系统指标时,这部分额外增加的时间仍在可以接受的范围之类。进一步考虑到AOP方式实现可以降低模块之间的耦合性,避免代码分散和混乱,在代码量方面可以缩减很多,而且降低了整个项目的复杂度,所以在具体Java Web项目开发中,如果对运行时间要求不是特别苛刻的话,恰当地使用AOP可以提高开发效率。 作为OOP思想的补充,AOP在软件开发中扮演着越来越重要的角色。从提出到现在,AOP的研发是迅速的,且慢慢趋向于成熟。它不是一种取代OOP的技术,而是与OOP相互补充,它解决了OOP中横切关注面分散在核心业务逻辑代码中,无法进行模块化的问题。在未来的项目开发中,AOP将作为一种不可或缺的编程思想,渗透在各个应用领域。 [1]Sharwood S. A New Aspect to Programming?[EB/OL].http://www.techrepublic.com/article/a-new-aspect-toprogramming,2005-04-08 [2]O’Regan G. Introduction to Aspect-Oriented Programming[EB/OL]. http://www.onjava.com./pub/a/onjava/2004/01/14/aop.html,2004-01-14 [3]Johnson R, Juergen Hoeller.Expert One-on-One J2EE Development without EJB[M].Indianapolis, Indiana: Wiley Publishing,Inc,2004 [4]孟凡新,张京军,刘光远.基于AOP和WEB服务的多层分布式系统[J].计算机工程,2010,36 (1):61-63 [5]肖荣,张云华.基于AOP 和反射计算的动态适应中间件[J].计算机系统应用,2010,9(1):58-62 [6]骆四毛,周兴斌.AOP对软件复杂度的影响分析及应用[J].计算机工程与设计,2013,34(5):1 822-1 825 [7]肖露,龙鹏飞.基于JAVA的动态代理实现的AOP的研究[J].微计算机信息,2011,27(2):211-2134 结 语