AOP技术在Javaq_下是最先得到应用的。就在PARC对于面向斚w~程q行研究的同Ӟ国Northeastern University的博士生Cristina Lopes和其同事也开始了cM的思考。最l,国国防先进技术研I计划vQDefense Advanced Research Projects Agency即DARPAQ注意到了这工作,q提供了U研l费Q鼓励将二者的工作成果l合h。他们通过定义一套Java语言的扩展系l,使开发者可以方便的q行面向斚w的开发,q套扩展pȝ被称为AspectJ。之后,AspectJ?002q被转让lEclipse FoundationQ从而成为在开源社ZAOP技术的先锋Q也是目前最为流行的AOP工具?/p>
AspectWerkz则是ZJava的动态的、轻量AOP框架。AspectWerkz仍然是开源社Z的品,由BEA System提供赞助Q开发者则是BEA的两名员工Jonas Bonér和Alexandre Vasseur。最q版本是AspectWerkz 2.0?005q?月,AspectJ和AspectWerkz达成协议Q同意将二者的成果l合CP取其_֍创徏一个单一的工兗他们合作的W一个发布版本ؓAspectJ 5Q它扩展了AspectJ语言Q以支持ZAnnotation开发风D又支持cMAspectJ代码风格。AspectJ 5也ؓJava 5的语aҎ提供完全的AOP支持?/p>
在Java阵营中,商用软g刉商JBoss在其2004q推出的JBoss 4.0中,引入了AOP框架和组件。在JBoss 4.0中,用户可以在JBoss应用服务器外部单独用JBoss AOPQ该版本为JBoss AOP 1.0Q是?004q?0月发布的。在2005q_JBoss AOP框架又发布了1.3.0版本Q新版本对加载期l入QWeevQ和切点Qpoint cutQ匹配的性能做了很大的优化,使应用程序的启动旉大大~短?/p>
作ؓd的FrameworkQSpring在开发轻量的J2EEӞ应用是非常广泛的。它通过IoC模式QInversion of ControlQ控制反转模式)来实现AOPQ通常被称为Spring AOP。在2004q_被作为Spring框架的扩展而发布,目前版本已更新到1.1.3。Spring AOP作ؓ一U非늕性的Q轻型的AOP框架Q开发者无需使用预编译器或其他的元标{,在JavaE序中应用AOP。目前,AOP的功能完全集成到了Spring事务理、日志和其他各种Ҏ的上下文中?/p>
?Net的阵营中QAOP技术的应用q不如Java阵营对AOP的关注?005q?月,微Y发布的Enterprise Library提供?U不同的“应用程序块Qapplication blocksQ”。有个别专家认ؓQ这些组件可以被认ؓ是方面。但该观点ƈ未得C致的认同。事实上Q在.Netq_下,推动AOP技术发展的原动力ƈ非微软,而是开源社区。虽Ӟ微Y的技术专家们亦然听到了在.Net Framework中增加AOP技术的众呼声Q但作ؓ如此巨大的Y件公司,要让它灵zd转变战略方向Q显然是不太现实的。正因ؓ此,才赐予了开源社区在AOP技术的研究与探索上一个巨大的发展I间?/p>
与Java阵营中的AOP技术不同,目前?Netq_下的各种AOP工具Q基本上q停留在实验室阶Dc但一些在技术上领先且逐渐成熟的AOP产品Q也在开源社Z渐露峥嵘。这其中主要包括Aspect#QAspectDNGQEos AOP{?/p>
Aspect#是基于Castle动态代理技术来实现的。Castle源于Apache Avalon目Q其目的在于实现一个轻量的IoC容器。Aspect#?005q?月被收录为Castle的其中一个子目。它是针对CLIQ?Net和MonoQ实现的AOP框架Q利用了反射、代理等机制。目前的Aspect#版本?.1.1?/p>
AspectDNG目前的版本ؓ0.7Q仍然处于beta版的阶段。它的实现技术是Zrail的静态织入。Rail属于ILU别下的代码l入Q它自定义的一套xml格式的ILML语言Q能够将原有的程序集拆散成ILML格式Q以便于寚w态程序集q行修改和扩展,从而达到静态织入的目的。因为AspectDNG是属于ILU别下的代码l入Q因此在.Netq_下,q不受具体的~程语言限制?/p>
Eos AOP与AspectDNG一P仍然采用静态织入的方式Q但从语法定义上Q它更近gAspectJ关于AOP的实现。它扩展了C#语法Q引入了aspect、introduce、before、after{关键字Qƈ且提供了专用的Eos~译器。Eos目是于2004q?月开始启动,2005q?月推出的0.3.3版本为最新版本,主要的开发h员ؓHridesh Rajan和Kevin Sullivan。前者ؓVirginia大学计算机系的研I生QEos目最初是由Hridesh Rajan提出的;而后者则计算机系的副教授QAssociate ProfessorQ。所以自Eos诞生之初Q就带有厚的学院派特色?/p>
从AOP技术的整体发展来看Q高性能、稳定、可扩展、易用的AOP框架是其势与目标。从上述对各UAOP技术的分析来看QAOP技术无疑是h共同特点的,而各U实现技术就是围l着q些共性深入与延。接下来Q我概要地介绍AOP的本质,以及它的技术要素?/p>
2.2 AOP技术本?/p>
2.2.1 技术概?/p>
AOPQAspect-Oriented ProgrammingQ面向方面编E)Q可以说是OOPQObject-Oriented ProgramingQ面向对象编E)的补充和完善。OOP引入装、承和多态性等概念来徏立一U对象层ơ结构,用以模拟公共行ؓ的一个集合。当我们需要ؓ分散的对象引入公p为的时候,OOP则显得无能ؓ力。也是_OOP允许你定义从上到下的关系Q但q不适合定义从左到右的关pR例如日志功能。日志代码往往水^地散布在所有对象层ơ中Q而与它所散布到的对象的核心功能毫无关pR对于其他类型的代码Q如安全性、异常处理和透明的持l性也是如此。这U散布在各处的无关的代码被称为横切(cross-cuttingQ代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用?/p>
而AOP技术则恰恰相反Q它利用一U称为“横切”的技术,剖解开装的对象内部,q将那些影响了多个类的公p为封装到一个可重用模块Qƈ其名ؓ“Aspect”,x面。所谓“方面”,单地_是那些与业务无关Q却Z务模块所共同调用的逻辑或责d装v来,便于减少pȝ的重复代码,降低模块间的耦合度,q有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系Q如果说“对象”是一个空心的圆柱体,其中装的是对象的属性和行ؓQ那么面向方面编E的ҎQ就仿佛一把利刃,这些空心圆׃剖开Q以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将q些剖开的切面复原,不留痕迹?/p>
使用“横切”技术,AOP把Y件系l分Z个部分:核心x点和横切x炏V业务处理的主要程是核心关注点Q与之关pM大的部分是横切关注点。横切关注点的一个特ҎQ他们经常发生在核心x点的多处Q而各处都基本怼。比如权限认证、日志、事务处理。Aop 的作用在于分ȝl中的各U关注点Q将核心x点和横切x点分d来。正如Avanade公司的高U方案构架师Adam Magee所_AOP的核心思想是“将应用E序中的商业逻辑同对其提供支持的通用服务q行分离。?/p>
实现AOP的技术,主要分ؓ两大c:一是采用动态代理技术,利用截取消息的方式,对该消息q行装饰Q以取代原有对象行ؓ的执行;二是采用静态织入的方式Q引入特定的语法创徏“方面”,从而得编译器可以在编译期间织入有关“方面”的代码。然而殊途同归,实现AOP的技术特性却是相同的Q分别ؓQ?/p>
1、join pointQ连接点Q:是程序执行中的一个精执行点Q例如类中的一个方法。它是一个抽象的概念Q在实现AOPӞq不需要去定义一个join point?br />2、point cutQ切入点Q:本质上是一个捕莯接点的结构。在AOP中,可以定义一个point cutQ来捕获相关Ҏ的调用?br />3、adviceQ通知Q:是point cut的执行代码,是执行“方面”的具体逻辑?br />4、aspectQ方面)Qpoint cut和advicel合h是aspectQ它cM于OOP中定义的一个类Q但它代表的更多是对象间横向的关pR?br />5、introduceQ引入)Qؓ对象引入附加的方法或属性,从而达C改对象结构的目的。有的AOP工具又将其称为mixin?/p>
上述的技术特性组成了基本的AOP技术,大多数AOP工具均实Cq些技术。它们也可以是研IAOP技术的基本术语?/p>
2.2.2 横切技?/p>
“横切”是AOP的专有名词。它是一U蕴含强大力量的相对单的设计和编E技术,其是用于徏立松散耦合的、可扩展的企业系l时。横切技术可以得AOP在一个给定的~程模型中穿既定的职责部分Q比如日志记录和性能优化Q的操作?/p>
如果不用横切技术,软g开发是怎样的情形呢Q在传统的程序中Q由于横切行为的实现是分散的Q开发h员很隑֯q些行ؓq行逻辑上的实现或更攏V例如,用于日志记录的代码和主要用于其它职责的代码缠l在一赗根据所解决的问题的复杂E度和作用域的不同,所引v的乱可大可。更改一个应用程序的日志记录{略可能涉及数百ơ编辑——即使可行,q也是个令h头疼的Q务?/p>
在AOP中,我们这些具有公共逻辑的,与其他模块的核心逻辑U缠在一L行ؓUCؓ“横切关注点QCrosscutting ConcernQ”,因ؓ它跨了l定~程模型中的典型职责界限?/p>
2.2.2.1 横切x?/p>
一个关注点QconcernQ就是一个特定的目的Q一块我们感兴趣的区域,一D|们需要的逻辑行ؓ。从技术的角度来说Q一个典型的软gpȝ包含一些核心的x点和pȝU的x炏VD个例子来_一个信用卡处理pȝ的核心关注点是借贷/存入处理Q而系l的关注点则是日志、事务完整性、授权、安全及性能问题{,许多x点——即横切x点(crosscutting concernsQ——会在多个模块中出现。如果用现有的~程ҎQ横切关注点会横多个模块,l果是ɾpȝ难以设计、理解、实现和演进。AOP能够比上q方法更好地分离pȝx点,从而提供模块化的横切关注点?/p>
例如一个复杂的pȝQ它p多关注点l合实现Q如业务逻辑、性能Q数据存储、日志和调度信息、授权、安全、线E、错误检查等Q还有开发过E中的关注点Q如易懂、易l护、易q查、易扩展{,?.1演示了由不同模块实现的一批关注点l成一个系l?/p>
?.1 把模块作Z批关注点来实?/p>
通过对系l需求和实现的识别,我们可以模块中的这些关注点分ؓQ核心关注点和横切关注点。对于核心关注点而言Q通常来说Q实现这些关注点的模块是怺独立的,他们分别完成了系l需要的商业逻辑Q这些逻辑与具体的业务需求有兟뀂而对于日志、安全、持久化{关注点而言Q他们却是商业逻辑模块所共同需要的Q这些逻辑分布于核心关注点的各处。在AOP中,诸如q些模块Q都UCؓ横切x炏V应用AOP的横切技术,关键是要实现对x点的识别?/p>
如果整个模块比Mؓ一个圆׃Q那么关注点识别q程可以用三镜法则来Ş容,I越三棱镜的光束Q指需求)Q照到圆柱体各处,获得不同颜色的光束,最后识别出不同的关注点。如?.2所C:
?.2 x点识别:三棱镜法?/p>
上图识别出来的关注点中,Business Logic属于核心x点,它会调用到SecurityQLoggingQPersistence{横切关注点?/p>
public class BusinessLogic
{
public void SomeOperation()
{
//验证安全性;Securtityx点;
//执行前记录日志;Loggingx点;
DoSomething();
//保存逻辑q算后的数据QPersistencex点;
//执行l束记录日志QLoggingx点;
}
}
AOP的目的,是要将诸如Logging之类的横切关注点从BusinessLogiccM分离出来。利用AOP技术,可以对相关的横切x点封装,形成单独的“aspect”。这׃证了横切x点的复用。由于BusinessLogiccM不再包含横切x点的逻辑代码Qؓ辑ֈ调用横切x点的目的Q可以利用横切技术,截取BusinessLogiccM相关Ҏ的消息,例如SomeOperation()ҎQ然后将q些“aspect”织入到该方法中。例如图2.3Q?/p>
?.3 横切关注点l入到核心关注点?/p>
通过利用AOP技术,改变了整个系l的设计方式。在分析pȝ需求之初,利用AOP的思想Q分d核心x点和横切x炏V在实现了诸如日志、事务管理、权限控制等横切x点的通用逻辑后,开发h员就可以专注于核心关注点Q将_֊投入到解决企业的商业逻辑上来。同Ӟq些装好了的横切关注点提供的功能,可以最大限度地复用于商业逻辑的各个部分,既不需要开发h员作Ҏ的编码,也不会因ZҎ切关注点的功能而媄响具体的业务功能?/p>
Z建立松散耦合的、可扩展的企业系l,AOP应用到的横切技术,通常分ؓ两种cdQ动态横切和静态横切?/p>
2.2.2.2 动态横?/p>
动态横切是通过切入点和q接点在一个方面中创徏行ؓ的过E,q接点可以在执行时横向地应用于现有对象。动态横切通常用于帮助向对象层ơ中的各U方法添加日志记录或w䆾认证。在很多应用场景中,动态横切技术基本上代表了AOP?/p>
动态横切技术的核心主要包括join pointQ连接点Q,point cutQ切入点Q,adviceQ通知Q和aspectQ方面)。在前面Q我已经概要Cl了q些术语分别代表的含义。接下来Q我以一个具体的实例来进一步阐q它们在AOP动态横切中实现的意义?/p>
考虑一个电子商务系l,需要对订单q行d、删除等理操作。毫无疑问,在实际的应用场景中,q些行ؓ应与权限理l合Q只有获得授权的用户方能够实施这些行为。采用传l的设计ҎQ其伪代码如下:
public class OrderManager
{
private ArrayList m_Orders;
public OrderManager()
{
m_Orders = new ArrayList();
}
public void AddOrder(Order order)
{
if (permissions.Verify(Permission.ADMIN))
{
m_Orders.Add(order);
}
}
public void RemoveOrder(Order order)
{
if (permissions.Verify(Permission.ADMIN))
{
m_Orders.Remove(order);
}
}
}
同样的,在该电子商务pȝ中,q需要对商品q行理Q它采用了同L授权机制Q?br />public class ProductManager
{
private ArrayList m_Products;
public ProductManager()
{
m_Products = new ArrayList();
}
public void AddProduct(Product product)
{
if (permissions.Verify(Permission.ADMIN))
{
m_Products.Add(product);
}
}
public void RemoveProduct(Product product)
{
if (permissions.Verify(Permission.ADMIN))
{
m_Products.Remove(product);
}
}
}
如此以来Q在整个电子商务pȝ中,核心业务包括订单理和商品管理,它们都需要相同的权限理Q如?.4所C:
?.4 电子商务pȝ的权限验证实?/p>
毫无疑问Q利用AOP技术,我们可以分离出系l的核心x点和横切x点,从横向的角度Q截取业务管理行为的内部消息Q以辑ֈl入权限理逻辑的目的。当执行AddOrder(){方法时Q系l将验证用户的权限,调用横切x炚w辑Q因此该Ҏ即ؓAOP的join point。对于电子商务系l而言Q每个需要权限验证的Ҏ都是一个单独的join point。由于权限验证将在每个方法执行前执行Q所以对于这一pdjoin pointQ只需要定义一个point cut。当pȝ执行到join point处时Q将Ҏ定义L扑֯应的point cutQ然后执行这个横切关注点需要实现的逻辑Q即advice。而point cut和adviceQ就l合成了一个权限管理aspect?/p>
?.5 AOP动态横切的技术实?/p>
׃aspect是一个封装的对象Q我们可以定义这样一个aspectQ?br />private static aspect AuthorizationAspect{……}
然后在这个aspect中定义point cutQ在point cut中,定义了需要截取上下文消息的方法,例如Q?br />private pointcut authorizationExecution():
execution(public void OrderManager.AddOrder(Order)) ||
execution(public void OrderManager.DeleteOrder(Order)) ||
execution(public void ProductManager.AddProduct(Product)) ||
execution(public void ProductManager.DeleteProduct(Product));
׃权限验证是在订单理Ҏ执行之前完成Q因此在before advice中,定义权限查:
before(): authorizationExecution()
{
if !(permissions.Verify(Permission.ADMIN))
{
throw new UnauthorizedException();
}
}
通过定义了这样一个完整的aspectQ当pȝ调用OrderManager或ProductManager的相x法时Q就触发了point cutQ然后调用相应的advice逻辑。如此以来,OrderManager和ProductManager模块׃权限理模块完全解除了依赖关p,同时也消除了传统设计中不可避免的权限判断的重复代码。这对于建立一个松散耦合、可扩展的系lY件是非常有利的?/p>
2.2.2.3 静态横?/p>
静态横切和动态横切的区别在于它不修改一个给定对象的执行行ؓ。相反,它允讔R过引入附加的方法字D和属性来修改对象的结构。此外,静态横切可以把扩展和实现附加到对象的基本结构中。在AOP实现中,通常静态横切称为introduce或者mixin?/p>
静态横切在AOP技术中Q受到的x相对较少。事实上Q这一技术蕴含的潜力是巨大的。用静态横切,架构师和设计者能用一U真正面向对象的Ҏ有效地徏立复杂系l的模型。静态横切允许您不用创徏很深的层ơ结构,以一U本质上更优雅、更逼真于现实结构的方式Q插入跨整个系l的公共行ؓ。尤其是当开发应用系l时Q如果需要在不修改原有代码的前提下,引入W三方品和API库,则静态横切技术将发挥巨大的作用?/p>
举例来说Q当前已l实C一个邮件收发系l,其中cMail完成了收发邮件的功能。但在品交付后Q发现该pȝ存在~陷Q在收发邮gӞ未曾实现邮g地址的验证功能。现在,W三方品已l提供了验证功能的接口IValidatableQ?br />public interface IValidatable
{
bool ValidateAddress();
}
我们可以利用设计模式中的Adapter模式Q来完成对第三方产品API的调用。我们可以定义一个新的类MailAdapterQ该cdCIValidatable接口Q同时承了Mailc:
public class MailAdapter:Mail,IValidatable
{
public bool ValidateAddress()
{
if(this.getToAddress() != null)
{
return true;
}
else
{
return false;
}
}
}
通过引入MailAdapterc,原来Mail对象完成的操作,全部被MailAdapter对象取代。然而,此种实现方式虽然能解军_入新接口的问题,但类g面的代码Q却是无法编译通过的:
Mail mail = new Mail();
IValidatable validate = ((IValidatable)mail).ValidateAddress();
必须第一行代码作如下修改Q?br />Mail mail = new MailAdapter();
利用AOP的静态横切技术,可以IValidatable接口l入到原有的MailcMQ这是一U非常Ş象的introduce功能Q其实现仍然是在aspect中完成:
import com.acme.validate.Validatable;
public aspect MailValidateAspect
{
declare parents: Mail implements IValidatable;
public boolean Mail.validateAddress()
{
if(this.getToAddress() != null)
{
return true;
}
else
{
return false;
}
}
}
静态横切的ҎQƈ没有引入cMMailAdapter的新c,而是通过定义的MailValidateAspect斚wQ利用横切技术ؓMailcintroduce了新的方法ValidateAddress()Q从而实CMail的扩展。因此如下的代码完全可行?br />Mail mail = new Mail();
IValidatable validate = ((IValidatable)mail).ValidateAddress();
2.3 AOP技术的优势
AOP技术的优势是显而易见的。在面向对象的世界里Qh们提Z各种Ҏ和设计原则来保障pȝ的可复用性与可扩展性,以期建立一个松散耦合、便于扩展的软gpȝ。例如GOF提出的“设计模式”,为我们提供了设计的典范与准则。设计模式通过最大程度的利用面向对象的特性,诸如利用l承、多态,对责任进行分R对依赖q行倒置Q面向抽象,面向接口Q最l设计出灉|、可扩展、可重用的类库、组Ӟ乃至于整个系l的架构。在设计的过E中Q通过各种模式体现对象的行为、暴露的接口、对象间关系、以及对象分别在不同层次中表现出来的形态。然而鉴于对象封装的Ҏ性,“设计模式”的触角始终在接口与抽象中大做文章,而对于对象内部则无能为力?/p>
通过“横切”技术,AOP技术就能深入到对象内部M覆雨Q截取方法之间传递的消息为我所用。由于将核心x点与横切x点完全隔,使得我们能够独立的对“方面”编E。它允许开发者动态地修改静态的OO模型Q构造出一个能够不断增长以满新增需求的pȝQ就象现实世界中的对象会在其生命周期中不断改变自w,应用E序也可以在发展中拥有新的功能?/p>
设计软gpȝ时应用AOP技术,其优势在于:
Q一Q在定义应用E序ҎU服务(例如日志Q的所有需求的时候。通过识别x点,使得该服务能够被更好的定义,更好的被~写代码Qƈ获得更多的功能。这U方式还能够处理在代码涉及到多个功能的时候所出现的问题,例如改变某一个功能可能会影响到其它的功能Q在AOP中把q样的麻烦称之ؓ“纠l(tanglingQ”?/p>
Q二Q利用AOP技术对L的方面进行的分析有助于为开发团队指定一位精于该工作的专家。负责这工作的最佳h选将可以有效利用自己的相x能和l验?/p>
Q三Q持久性。标准的面向对象的项目开发中Q不同的开发h员通常会ؓ某项服务~写相同的代码,例如日志记录。随后他们会在自q实施中分别对日志q行处理以满不同单个对象的需求。而通过创徏一D单独的代码片段QAOP提供了解册一问题的持久简单的ҎQ这一Ҏ了未来功能的重用性和易维护性:不需要在整个应用E序中一遍遍重新~写日志代码QAOP使得仅仅~写日志斚wQlogging aspectQ成为可能,q且可以在这之上为整个应用程序提供新的功能?/p>
总而言之,AOP技术的优势使得需要编写的代码量大大羃减,节省了时_控制了开发成本。同时也使得开发h员可以集中关注于pȝ的核心商业逻辑。此外,它更利于创徏松散耦合、可复用与可扩展的大型Y件系l?/p>