面向方面编程 (AOP,Aspect Oriented Programming) 是施乐公司帕洛阿尔托研究中心 (Xerox PARC) 在上世纪90年代创建的一种编程范式,问世的近十年里,除了极少数时间,AOP在大多数情况下都是归于沉寂。然而这段时间,业内许多人开始谈论AOP,越来越多的技术人员逐渐意识到AOP的巨大优势以及它潜在的力量,而企业的IT部门则想了解AOP将会对他们的应用程序体系结构产生何种影响。
近年来,随着计算机技术的快速发展和应用的不断普及,传统的整体设计和集中控制的软件开发方法也就越来越显示出其固有的局限性。
面向对象编程(OOP,Object Oriented Programming)技术的出现在很大程度上解决了现实中存在的部分问题,对于软件系统的开发方式产生了极大的影响。通过OOP,软件开发者可以利用一组实体以及这些实体相互之间的关系将系统形象地表示出来,其目的是设计出规模更大、更复杂、应用更广泛的系统,而软件开发周期也比以前未采用OOP时短得多。
OOP的桎梏
OOP的编程思路比较简单。和早期那些传统的编程技术一样,从某些方面来看,OOP采用的具体方法是用分解的方式,将完整的软件系统划分为相对较小的、易于分析和理解的模块,如果这些模块在一次分解后仍然难以分析、理解,那么就进行多次分解,将其分解为更小的模块,直至这些模块可以进行分析、理解,从而方便地进行各个功能模块的设计和编码。这种做法的初衷并没有错,但是如果我们将实现系统业务功能的模块看做系统的纵向分解单元的话,那么问题也就来了。通过简单的分析,我们可以看出,上述分散在功能模块中的功能与行为之间形成了一种横向的方面(Aspect),而方面与模块形成了横切(Crosscutting),继而造成传统的编程技术无法将方面模块化,两种代码纠结(Tangling)在一起。造成代码纠结的原因是在传统的编程技术中,软件系统中非业务功能实现的代码无法模块化,它们散布在实现业务功能的代码中,继而造成这种情况。
与此同时,OOP的问题还在于,它在本质上是静态的,因此需求上的任何细微变化都有可能对软件开发的整体进度造成重大影响。
什么是AOP
Avanade公司的高级方案构架师Adam Magee认为,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离”。
越来越多的开发者认为,AOP是对OOP技术的补充和完善。相对于以往包括OOP在内的其他编程范式,AOP方法具有很多优点。首先,由于其先进的理念,程序员无需花费大量的时间重复编写相同的代码;其次,操作更为简捷,带来的则是性能的有效提升;同时,AOP能够为不同过程提供更好的封装性,提高未来的互操作性。借助面向方面编程,开发人员可以用与封装组件本身相同的方式跨组件封装公共服务。
在AOP中,将两种代码混合的机制称为织入(Weaving),实现这一机制的工具称为织入器(Weaver)。因此,对方面单独进行编码,并通过适当的织入机制使两种代码混合,就构成了AOP解决代码纠结问题的基石。
AOP允许开发者动态地修改静态的OO模型,构造出一个能够不断增长以满足新增需求的系统,开发者不必修改原来的静态模型也可以加入满足第二需求所需的代码,就像现实世界中的对象会在其生命周期中不断改变自身,应用程序也可以在发展中拥有新的功能。尤为令人称道的是,这些后来加入的代码往往可以集中在整个软件架构的某个地方,而不必像单纯使用OOP时那样将后来加入的代码分散到整个模型中。
C#拉了AOP一把
至少在字面上了解了AOP的特性后,许多软件架构师和程序员都表示很喜欢AOP的理念。然而我们知道,任何技术的早期实现都是非常重要的,如果它只是一味停留在理念层面,那么最后的结果往往是被投进废纸篓。1997年问世的AOP也曾遭遇到这种危险,它没有引起有关方面更多的关注,即便是少部分人抱有一点儿兴趣,也往往是浅尝辄止,并没有深入其实质。AOP的命运,一度令人揪心。
令人庆幸的是,此时上演的一幕改变了AOP所面临的不利开局:从1995年Sun公司的Java语言问世伊始,微软就一直试图用C#超越Java(尽管C#也模仿了大量的Java特性)。微软的努力并没有白费,C#得到了越来越多开发者的青睐,开始广泛收获市场。于是,Java也必须从某些方面进行改进,除了提供更加易用的开发工具来和Visual Studio .NET竞争之外,Java的一些开发者们也在考虑让Java拥有一种更加高级的开发语言。最终,他们的目光定格在AOP上,由此AOP也终于得到了包括IBM在内的很多公司和组织的高度重视,现在已经有一些组织和厂商试图建立有关AOP的标准。业内人士预计,如果AOP真的成为Java的标准功能,那么Java就极有可能成为比微软的.Net更具吸引力的开发语言。因此,如果以后AOP真的能够全面“开花结果”,还应该感谢微软的C#多年来对Java的步步紧逼。
图 AOP实现模型示意
AOP的具体实现
根据来自于AOSD(Aspect Oriented Software Development)的统计,目前与AOP相关的项目已达百种左右,而基于Java的AOP实现机制也有数十种之多,以下列举四种在商业上业已得到成熟应用的基于Java的AOP实现机制。
首先是AspectJ,它被很多人认为是目前最完善的AOP语言,由AOP的首倡者Gregor Kiczales领导的一个小组提出并得到发展。AspectJ是对Java编程语言的扩展,通过增加了一些新的构造块支持对横切关注点的模块化封装,通过对源代码级别的代码混合实现织入,是一种典型的使用静态织入的AOP实现机制。目前,AspectJ既支持编译前的预处理方式实现代码的织入,也支持编译后的字节码操作。
第二种是AspectWerkz(模型图参见附图,相关注解见文末),它由Jonas Boner和Alexandre Vasseur创建,是目前最快速、功能最丰富的框架之一。AspectWerkz被认为可能是最容易学习的框架,也是最容易集成到现有项目的框架,它利用对字节码的修改实现方面(Aspect)的织入(Weave),并使用Java虚拟机的动态替换字节码的能力实现动态AOP的要求。通过方面容器与织入模型,AspectWerkz提供了动态AOP的实现。
第三种是SpringFramework,它是一种采用了反转控制(Inversion of Control, IoC)策略的基于J2EE的轻量级应用框架。SpringFramework中AOP的实现基于动态代理(Dynamic Proxy), 动态代理源于代理模式。SpringFramework除自身实现的AOP框架外,还在寻求与其他AOP实现机制的整合,目前已经实现了与AspectJ的整合,以利用AspectJ丰富的切入点语法,并利用AspectJ的方面实现。
最后一种是JBoss,它是一个开源的符合J2EE规范的应用服务器,作为J2EE规范的补充,Jboss中引入了AOP框架,为普通Java类提供了J2EE服务,而无需遵循EJB规范。Jboss中的参考、切入点与方面也由普通Java对象实现,并使用XML文件配置。
结 语
应该说,AOP这个领域还很新,未来可能会有越来越多的大型项目采纳AOP。从某种意义上来看,AOP并不是一种取代传统编程技术的技术,而是对这些技术的有机补充,它解决了一些传统技术无法很好处理的问题。对IT部门来说,一个特征全面的AOP架构,也将显示出EJB的强大功能,并给更加广阔的用户群带来真正意义上的企业级开发,IT部门可以施行更广泛的服务,并且从更高的效率和更快的发展中获利。
AOP之路,越走越宽。
注解
Servlet: 使用Java Servlet应用程序设计接口(API)及相关类和方法的Java程序。除了 Java Servlet API,Servlet 还可以使用用以扩展和添加到API的Java类软件包。
EJB: Enterprise JavaBeans,J2EE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准。其特点包括网络服务支持和核心开发工具(SDK)。
DAO: Data Access Object,数据访问对象,通常定义成接口。由于所要访问的数据保存在不同的数据源中,但商业逻辑相同,所以通过实现相同的接口达到访问不同数据源的目的。
P6Log: 一个应用程序,可以记录任何Java应用程序中所有的JDBC事务。
JDBC: Java Database Connectivity,Java数据库连接。
近年来,随着计算机技术的快速发展和应用的不断普及,传统的整体设计和集中控制的软件开发方法也就越来越显示出其固有的局限性。
面向对象编程(OOP,Object Oriented Programming)技术的出现在很大程度上解决了现实中存在的部分问题,对于软件系统的开发方式产生了极大的影响。通过OOP,软件开发者可以利用一组实体以及这些实体相互之间的关系将系统形象地表示出来,其目的是设计出规模更大、更复杂、应用更广泛的系统,而软件开发周期也比以前未采用OOP时短得多。
OOP的桎梏
OOP的编程思路比较简单。和早期那些传统的编程技术一样,从某些方面来看,OOP采用的具体方法是用分解的方式,将完整的软件系统划分为相对较小的、易于分析和理解的模块,如果这些模块在一次分解后仍然难以分析、理解,那么就进行多次分解,将其分解为更小的模块,直至这些模块可以进行分析、理解,从而方便地进行各个功能模块的设计和编码。这种做法的初衷并没有错,但是如果我们将实现系统业务功能的模块看做系统的纵向分解单元的话,那么问题也就来了。通过简单的分析,我们可以看出,上述分散在功能模块中的功能与行为之间形成了一种横向的方面(Aspect),而方面与模块形成了横切(Crosscutting),继而造成传统的编程技术无法将方面模块化,两种代码纠结(Tangling)在一起。造成代码纠结的原因是在传统的编程技术中,软件系统中非业务功能实现的代码无法模块化,它们散布在实现业务功能的代码中,继而造成这种情况。
与此同时,OOP的问题还在于,它在本质上是静态的,因此需求上的任何细微变化都有可能对软件开发的整体进度造成重大影响。
什么是AOP
Avanade公司的高级方案构架师Adam Magee认为,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离”。
越来越多的开发者认为,AOP是对OOP技术的补充和完善。相对于以往包括OOP在内的其他编程范式,AOP方法具有很多优点。首先,由于其先进的理念,程序员无需花费大量的时间重复编写相同的代码;其次,操作更为简捷,带来的则是性能的有效提升;同时,AOP能够为不同过程提供更好的封装性,提高未来的互操作性。借助面向方面编程,开发人员可以用与封装组件本身相同的方式跨组件封装公共服务。
在AOP中,将两种代码混合的机制称为织入(Weaving),实现这一机制的工具称为织入器(Weaver)。因此,对方面单独进行编码,并通过适当的织入机制使两种代码混合,就构成了AOP解决代码纠结问题的基石。
AOP允许开发者动态地修改静态的OO模型,构造出一个能够不断增长以满足新增需求的系统,开发者不必修改原来的静态模型也可以加入满足第二需求所需的代码,就像现实世界中的对象会在其生命周期中不断改变自身,应用程序也可以在发展中拥有新的功能。尤为令人称道的是,这些后来加入的代码往往可以集中在整个软件架构的某个地方,而不必像单纯使用OOP时那样将后来加入的代码分散到整个模型中。
C#拉了AOP一把
至少在字面上了解了AOP的特性后,许多软件架构师和程序员都表示很喜欢AOP的理念。然而我们知道,任何技术的早期实现都是非常重要的,如果它只是一味停留在理念层面,那么最后的结果往往是被投进废纸篓。1997年问世的AOP也曾遭遇到这种危险,它没有引起有关方面更多的关注,即便是少部分人抱有一点儿兴趣,也往往是浅尝辄止,并没有深入其实质。AOP的命运,一度令人揪心。
令人庆幸的是,此时上演的一幕改变了AOP所面临的不利开局:从1995年Sun公司的Java语言问世伊始,微软就一直试图用C#超越Java(尽管C#也模仿了大量的Java特性)。微软的努力并没有白费,C#得到了越来越多开发者的青睐,开始广泛收获市场。于是,Java也必须从某些方面进行改进,除了提供更加易用的开发工具来和Visual Studio .NET竞争之外,Java的一些开发者们也在考虑让Java拥有一种更加高级的开发语言。最终,他们的目光定格在AOP上,由此AOP也终于得到了包括IBM在内的很多公司和组织的高度重视,现在已经有一些组织和厂商试图建立有关AOP的标准。业内人士预计,如果AOP真的成为Java的标准功能,那么Java就极有可能成为比微软的.Net更具吸引力的开发语言。因此,如果以后AOP真的能够全面“开花结果”,还应该感谢微软的C#多年来对Java的步步紧逼。
图 AOP实现模型示意
AOP的具体实现
根据来自于AOSD(Aspect Oriented Software Development)的统计,目前与AOP相关的项目已达百种左右,而基于Java的AOP实现机制也有数十种之多,以下列举四种在商业上业已得到成熟应用的基于Java的AOP实现机制。
首先是AspectJ,它被很多人认为是目前最完善的AOP语言,由AOP的首倡者Gregor Kiczales领导的一个小组提出并得到发展。AspectJ是对Java编程语言的扩展,通过增加了一些新的构造块支持对横切关注点的模块化封装,通过对源代码级别的代码混合实现织入,是一种典型的使用静态织入的AOP实现机制。目前,AspectJ既支持编译前的预处理方式实现代码的织入,也支持编译后的字节码操作。
第二种是AspectWerkz(模型图参见附图,相关注解见文末),它由Jonas Boner和Alexandre Vasseur创建,是目前最快速、功能最丰富的框架之一。AspectWerkz被认为可能是最容易学习的框架,也是最容易集成到现有项目的框架,它利用对字节码的修改实现方面(Aspect)的织入(Weave),并使用Java虚拟机的动态替换字节码的能力实现动态AOP的要求。通过方面容器与织入模型,AspectWerkz提供了动态AOP的实现。
第三种是SpringFramework,它是一种采用了反转控制(Inversion of Control, IoC)策略的基于J2EE的轻量级应用框架。SpringFramework中AOP的实现基于动态代理(Dynamic Proxy), 动态代理源于代理模式。SpringFramework除自身实现的AOP框架外,还在寻求与其他AOP实现机制的整合,目前已经实现了与AspectJ的整合,以利用AspectJ丰富的切入点语法,并利用AspectJ的方面实现。
最后一种是JBoss,它是一个开源的符合J2EE规范的应用服务器,作为J2EE规范的补充,Jboss中引入了AOP框架,为普通Java类提供了J2EE服务,而无需遵循EJB规范。Jboss中的参考、切入点与方面也由普通Java对象实现,并使用XML文件配置。
结 语
应该说,AOP这个领域还很新,未来可能会有越来越多的大型项目采纳AOP。从某种意义上来看,AOP并不是一种取代传统编程技术的技术,而是对这些技术的有机补充,它解决了一些传统技术无法很好处理的问题。对IT部门来说,一个特征全面的AOP架构,也将显示出EJB的强大功能,并给更加广阔的用户群带来真正意义上的企业级开发,IT部门可以施行更广泛的服务,并且从更高的效率和更快的发展中获利。
AOP之路,越走越宽。
注解
Servlet: 使用Java Servlet应用程序设计接口(API)及相关类和方法的Java程序。除了 Java Servlet API,Servlet 还可以使用用以扩展和添加到API的Java类软件包。
EJB: Enterprise JavaBeans,J2EE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准。其特点包括网络服务支持和核心开发工具(SDK)。
DAO: Data Access Object,数据访问对象,通常定义成接口。由于所要访问的数据保存在不同的数据源中,但商业逻辑相同,所以通过实现相同的接口达到访问不同数据源的目的。
P6Log: 一个应用程序,可以记录任何Java应用程序中所有的JDBC事务。
JDBC: Java Database Connectivity,Java数据库连接。