第三只眼看AOP

本文仅介绍了自己对AOP的认识,没有技术含量啊,只是希望自己能够在AOP的大旗下,做个摇旗呐喊的小卒,借本文鼓吹一下AOP。不过,这种鼓吹有点反面的意思,然而却是自己较为冷静的思考。识见疏陋,希望大家不吝赐教。

本文发表与2005年《程序员》第五期,发表时略有删改。

什么是AOP

最初听到AOP这个名词,我总是错觉其与OOP是否具有孪生性?那么,所谓AOP,即面向方面编程(Aspect Oriented Programming),是否是面向对象编程的一种进化呢?关键就在于我们对“方面(Aspect)”的理解。确实,“方面”这个词语是够抽象的,简单地说,它就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

对于OOPBruce Eckel有一句名言,“Everything is Object.”确实,在程序的世界里,我们可以将万事万物定义为一种对象,并将这些对象的行为和属性封装起来,同时定义好对象与对象之间的关系。很显然,对于AOP而言,我们无法套用这句名言,妄言“Everything is Aspect.”实质上,AOP只是OOP的一种补充或某种改进,它转换了编程的范式和视角,关注了一直以来被OOP忽略或者说未能解决好的角落,使开发人员可以更好地将本不该彼此纠缠在一起的责任(如银行业务和事务处理)分离开来。通过面向方面的编程,可以将程序的责任分开,对象与方面互不干扰。面向方面的模块并非显式地为对象所调用,而是通过或注入或截取的方式,去获得被封装的对象内部方法间的消息,然后做出相应地处理。也许面向方面的模式破坏了对象的封装,却正其如此,方才能降低模块与模块之间的耦合度。同样地,通过对“方面”的封装,将这些通用的功能从不同的类中分离出来,使不同的模块都能共享同样的“方面”,这也极大地减少了重复代码。

如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

 

AOP,并不具有革命的驱动力

 

个人认为,AOP还谈不上是一种编程的思想,只能说是一种方法而已。溯其根源,一般认为,面向方面编程(AOP)是施乐公司帕洛阿尔托研究中心(Xerox PARC)在上世纪90年代发明的一种编程范式。它在OOP的缝隙之中,抽象出“方面”的概念,目的就是为了打破对象的封装性,以“方面”的方式对原有的模块进行重组,抽取那些与业务无关却为整个系统所通用的功能,最终封装在一起。

那么,最终封装好的这些所谓“方面”,如何被业务对象所调用呢?这就需要“方面”拥有截取封装对象消息的能力。在JAVA世界里,AOP的应用已经走向比较成熟的应用。AspectJSpring,在体现AOP能力上来说,已经渐趋成熟。甚至在JBOSS4.0中,已经引入了AOP框架进行开发,并在权限管理(Authentication)、错误处理(Error Handling)、事务处理(Transactions)、持久化(Persistence)等方面取得了很好的应用。在.Net平台下,对于AOP的应用似乎却走到了后面。在Microsoft 推出的.Net Framework 1.1中,并没有应用AOP,也未曾提供AOP的框架。不过.Net Framework仍然提供了实现AOP的技术可能,即通过.Net Framework的反射机制或.Net Remoting的代理机制获取元数据信息或对象内部间传递的消息。同时,我也看到开源社区中的AOP.Net项目,采用了非托管的.Net Profilling API,它采用了非托管的C++ COM组件,可以在相关事件发生时,通过.Net系统捕获其消息并发送通知。

AOP在企业应用中正逐渐体现其自身的价值。但正如其名,它的作用更多地是关注于系统的某一方面。AOP还缺乏革命的驱动力,并不足以颠覆OOP世界。我们不可能预见AOP之于OOP,象当初面向对象编程取代面向过程编程那样,具有强大至可以颠覆程序员思想的力量。而事实上,AOP从一诞生以来,就从未贴上“革命”的标签。相反,它更多地起到了推波助澜的作用,弥补着OOP的缺失,进而在OO程序设计中,扩展了一种更宽广的模式。

 

AOP,“设计模式”的延续

 

不错,AOP的目的,恰恰就是做了“设计模式”想做却一直未曾做到的功能。GOF的“设计模式”给了我们设计的典范与准则,通过最大程度的利用面向对象的特性,诸如利用继承、多态,对责任进行分离、对依赖进行倒置,面向抽象,面向接口,最终设计出灵活、可扩展、可重用的类库、组件,乃至于整个系统的架构。在设计的过程中,通过各种模式体现了对象的行为,暴露的接口,对象间关系,以及对象分别在不同层次中表现出来的形态。然而鉴于对象封装的特殊性,“设计模式”的触角始终在接口与抽象中大做文章,而对于对象内部则无能为力。

举例来说,我们需要为系统提供日志的能力。虽然我们可以通过装饰模式(Decorate Pattern),提供各种日志的组合,但不可避免的是,大量的日志对象实例代码的存在,导致了重复代码的坏味道,同时也导致了强依赖性,这并不利于模块间的解耦。如果我们通过AOP,将这些日志的功能看作是一个“方面”,然后将系统中需要日志能力的模块置于该“方面”的侦听之中,抽象出来的“方面”好像是一个容器,在其内部的世界里,不分贫富贵贱。只要执行了某种业务,这个容器就会忠实地记录这些模块间传递的消息。至于这些模块到底实现了何种业务,却并非“方面”所关注的。

前面已经叙述到,面向方面编程的价值主要体现在事务处理、日志管理、权限控制等与业务无关,却为业务模块所共同调用的逻辑或责任上,而这些所谓的“方面”,恰恰是企业应用时非常必须的。因此,与其说AOP是一种编程的技术,毋宁说AOP是一种企业的“设计模式”。它弥补了OOP之拙,却未曾也不可能超越OOP而单独存在。

posted @ 2005-08-23 10:40  张逸  阅读(6638)  评论(4编辑  收藏  举报