面向方面编程 (Aspect-oriented programming,AOP,又译作面向方面程序设计 、面向切面程序设计 、剖面导向程序设计 ),是计算机科学 中的一种编程范型 ,旨在将交叉切入关注 与作为业务主体的核心关注 进行分离,以提高程序代码的模块化 程度。“方面”(aspect)通过规定叫做“点切入”(pointcut)的一种量化或查询,在各种接合点(join point)上应用通告(advice),从而改变现有基础代码的行为(behavior)。比如点切入与通告的一个实例:“对所有方法名以set*
开头的方法添加后台日志”。该思想使得开发人员能够将与代码核心业务逻辑关系不那么密切的功能(如日志功能)添加至程序中,同时又不降低业务代码的可读性。
简介
面向方面编程将代码逻辑切分为不同的模块 (即关注 ,一段特定的逻辑功能)。几乎所有的编程思想都涉及代码功能的分类,将各项关注(concern)封装成独立的抽象模块(如函数、过程、模块、类以及方法等),后者又可供进一步实现、封装和重写。部分关注“交叉切入”程序代码中的数个模块,即在多个模块中都有出现,它们即被称作交叉切入关注 。
日志功能即是交叉切入关注的一个典型案例,因为日志功能往往跨越系统中的每个业务模块,即交叉切入(crosscut)所有有日志需求的类及方法体。而对于一个信用卡应用程序来说,存款、取款、帐单管理是它的核心关注,日志和持久化将成为交叉切入整个对象结构的交叉切入关注。
方面的概念源于对面向对象编程 和計算反射 的融合。面向方面编程语言拥有很多类似于元对象协议 的功能,但有更多的限制。方面相关的编程概念包括主题 、混入 和委托 。使用面向方面范型的其他方式有复合过滤器 和Hyper/J的hyperslices方式。
历史
“面向方面编程”这一术语由施乐 帕洛阿尔托研究中心 的Chris Maeda首先提出,但其具体时间已经不可考证了。术语“交叉切入”(crosscut)是由Gregor Kiczales 提出的。同许多重大的技术创新一样,面向方面编程,也是在不同的地方被独立发展出来。面向方面编程的早期工作,主要是由下面几个机构和人员作出的:
施乐 帕洛阿尔托研究中心 :Gregor Kiczales、John Lamping、Cristina Videira Lopes等人,进行的早期工作有关于反射机制 和元对象协议 ,在1997年Gregor Kiczales发表了论文《面向方面编程》[ 1] ;代表系统是基于元对象协议 的面向方面编程系统和AspectJ 。
国际商用机器公司 托马斯·J·沃森研究中心 :William Harrison、Harold Ossher、Peri Tarr等人,在1980年代末进行的早期工作,有关于软件开发环境与工具集成;后来提出了多维关注分离(MDSOC),代表系统是Hyper/J。
美国东北大学 :Karl Lieberherr等人,进行的早期工作是研究软件演化,提出了得墨忒耳定律 、传播模式、适应性编程[ 2] ;代表系统是Demeter/C++和Demeter/Java。
荷兰特文特大学 :Mehmet Aksit等人,其代表系统是复合过滤器 。
基本概念
关注 是对软件工程有意义的小的、可管理的、可描述的软件组成部分,一项关注通常只同一个特定概念或目标相关联。传统的编程语言,以一种线性的文本来描述软件,只采用一种方式比如类,将软件分解成模块;这导致某些关注比较好的被捕捉,容易进一步组合、扩展;但还有一些关注没有被捕捉,弥散在整个软件内部。
关注分离 (SOC)是标识、封装和操纵只与特定概念、目标相关联的软件组成部分的能力,即标识、封装和操纵关注的能力。分离关注使得解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑的代码中不再含有针对特定领域问题代码的调用,业务逻辑同特定领域问题的关系通方面来封装、维护,这样原本分散在在整个应用程序中的变动就可以很好的管理起来。
核心关注 是一个软件最主要的关注。在传统的编程语言中,将软件分解成模块的主要方式,是支配性分解,即按主关注进行模块分解。用来描述、设计、实现一项给定关注的软件构造单位是方法 。如果两个关注的实现的方法存在交集,则称谓这两个关注相互交叉切入(crosscut)。
面向方面编程的核心概念,是从核心关注 中分离出交叉切入关注 。面向方面编程,在支配性分解的基础上,提供叫做方面 (aspect)的一种辅助的模块化机制,这种新的模块化机制可以捕捉交叉切入关注。
接合点模型
面向方面编程语言的通告相关构件,定义了一个接合点模型(JPM)。一个JPM定义了三种东西:
何时通告可以运行。这些叫做接合点 ,因为在一个运行的程序中,它们是可以有用的接合上额外行为的点。一个接合点想要有用,它必需是可寻址的,并且对普通程序员是可理解的。它还应该经历无关紧要的程序变更而保持稳定,使得一个方面经历这种变更而保持稳定。很多AOP实现支持方法执行和字段引用作为接合点。
规定(或量化)接合点的方式,这叫做点切入 。点切入确定是否匹配一个给定接合点。最有用的点切入语言使用像基础语言的语法(例如AspectJ 使用Java签名 ),并允许通过命名和组合来重新使用。
指定在接合点要运行的代码的手段。AspectJ 称之为通告 ,并且可以在接合点之前、之后和周围运行。一些实现还支持在一个方面中定义另一个类上的一个方法。
对接合点模型进行比较可以基于:所暴露的接合点,如何规定接合点,在接合点上允许的操作,能够表达的结构性增强机制。
AspectJ的接合点模型
所有有效的Java程序也是有效的AspectJ程序,但是AspectJ容许编程者定义叫方面 的特殊构造。方面包含一些对于标准类不能获得到的实体。它们是扩展方法、点切入和通告。
扩展方法
扩展方法 允许编程者在这个方面之内向现存的类增加方法、字段或接口。下面例子中,方面VisitAspect
向类Point
增加一个acceptVisitor
方法(参见访问者模式 ):
aspect VisitAspect {
void Point . acceptVisitor ( Visitor v ) {
v . visit ( this );
}
⋮
}
点切入
在AspectJ中接合点包括:方法或构造子调用或执行,一个类或对象的初始化,字段读或写访问,异常处理等。接合点不包括:循环、super
调用,throw
子句,多个语句等。
点切入是通过组合“原始点切入指示符”(PCD - primitive pointcut designator)来规定的。例如:
aspect VisitAspect {
⋮
pointcut set () : execution ( * set * ( * ) ) && this ( Point ) && within ( com . company . * );
⋮
}
这个点切入匹配一个方法执行接合点,如果这个方法名字开始于set
,并且此对象(this
)是在com.company
包中类型Point
的实例。这个点切入可以使用名字set()
来提及。点切入可以复合和命名来重新使用。
“种类”PCD匹配特定种类的接合点(比如方法执行),并且倾向于接受类似Java模样的签名作为输入:
这个点切入匹配一个方法执行接合点,如果这个方法名字开始于set
,并且精确的只有一个任何类型的实际参数。
“动态”PCD检查运行时间类型和绑定变量:
这个点切入在当前执行对象是类Point
的实例之时匹配。注意一个类的未限定名字可以通过Java的正常类型查找来使用。
“范围”PCD限制接合点的词法作用域:
这个点切入匹配在com.company
包中任何类型的任何接合点。*
是一种形式的通配符,它用来匹配具有一个签名的任何东西。
通告
通告规定在(通过点切入指定的)一个接合点(之前、之后或周围)运行特定代码(指定如若一个方法中的代码)。面向方面编程的运行时间系统,在这个点切入匹配一个接合点的时候,自动调用通告。例如:
aspect VisitAspect {
⋮
after () : set () {
Display . update ();
}
}
这在效果上指定了:“如果set()
点切入匹配这个接合点,在接合点完成之后,运行代码Display.update()
。”
实现
下列编程语言 已经实现了AOP,于语言之内或外部库:
參考文獻
^ Kiczales, G. ; Lamping, J.; Mendhekar, A.; Maeda, C.; Lopes, C.; Loingtier, J. M.; Irwin, J. Aspect-oriented programming (PDF) . ECOOP '97. Proceedings of the 11th European Conference on Object-Oriented Programming. LNCS 1241 . 1997: 220–242. CiteSeerX 10.1.1.115.8660 . ISBN 3-540-63089-9 . doi:10.1007/BFb0053381 . (原始内容存档 (PDF) 于2016-01-12).
^ "Adaptive Object Oriented Programming: The Demeter Approach with Propagation Patterns" Karl Liebherr 1996 ISBN 0-534-94602-X presents a well-worked version of essentially the same thing (Lieberherr subsequently recognized this and reframed his approach).
^ Numerous:
Afterthought 互联网档案馆 的存檔 ,存档日期2016-03-15., LOOM.NET 互联网档案馆 的存檔 ,存档日期2008-08-27., Enterprise Library 3.0 Policy Injection Application Block 互联网档案馆 的存檔 ,存档日期2007-01-19., AspectDNG 互联网档案馆 的存檔 ,存档日期2004-09-29., DynamicProxy 互联网档案馆 的存檔 ,存档日期2015-12-05., Compose* Wikiwix的存檔 ,存档日期2005-08-21, PostSharp 互联网档案馆 的存檔 ,存档日期2016-05-03., Seasar.NET 互联网档案馆 的存檔 ,存档日期2006-07-25., DotSpect (.SPECT) 互联网档案馆 的存檔 ,存档日期2006-03-31., Spring.NET 互联网档案馆 的存檔 ,存档日期2006-04-02. (as part of its functionality), Wicca and Phx.Morph 互联网档案馆 的存檔 ,存档日期2006-12-07., SetPoint 互联网档案馆 的存檔 ,存档日期2008-10-07.
^ PostSharp . [2022-02-13 ] . (原始内容 存档于2022-07-05).
^ Welcome to as3-commons-bytecode . as3commons.org. [5 May 2018] . (原始内容存档 于3 October 2014).
^ Ada2012 Rationale (PDF) . adacore.com. [5 May 2018] . (原始内容存档 (PDF) 于18 April 2016).
^ Function Hooks . autohotkey.com. [5 May 2018] . (原始内容 存档于17 January 2013).
^ Several: AspectC++ , FeatureC++ (页面存档备份 ,存于互联网档案馆 ), AspectC 互联网档案馆 的存檔 ,存档日期2006-08-21., AspeCt-oriented C 互联网档案馆 的存檔 ,存档日期2008-11-20., Aspicere
^ Cobble . vub.ac.be. [5 May 2018] . [永久失效連結 ]
^ AspectCocoa . neu.edu. [5 May 2018] . (原始内容 存档于26 October 2007).
^ ColdSpring Framework: Welcome . 5 November 2005 [5 May 2018] . (原始内容 存档于5 November 2005).
^ Closer Project: AspectL. . [11 August 2015] . (原始内容存档 于23 February 2011).
^ infra - Frameworks Integrados para Delphi - Google Project Hosting . [11 August 2015] . (原始内容存档 于9 September 2015).
^ meaop - MeSDK: MeObjects, MeRTTI, MeAOP - Delphi AOP(Aspect Oriented Programming), MeRemote, MeService... - Google Project Hosting . [11 August 2015] . (原始内容存档 于10 September 2015).
^ Google Project Hosting . [11 August 2015] . (原始内容存档 于25 December 2014).
^ RemObjects Cirrus . codegear.com. [5 May 2018] . (原始内容 存档于23 January 2012).
^ Emacs Advice Functions . gnu.org. [5 May 2018] . (原始内容存档 于24 October 2011).
^ Monad s allow program semantics to be altered by changing the type of the program without altering its code: De Meuter, Wolfgang. Monads As a theoretical basis for AOP. International Workshop on Aspect-Oriented Programming at ECOOP. 1997: 25. CiteSeerX 10.1.1.25.8262 . Tabareau, Nicolas; Figueroa, Ismael; Tanter, Éric. A Typed Monadic Embedding of Aspects . Proceedings of the 12th Annual International Conference on Aspect-oriented Software Development. Aosd '13. March 2013: 171–184 [2022-03-02 ] . ISBN 9781450317665 . S2CID 27256161 . doi:10.1145/2451436.2451457 . (原始内容 存档于2018-11-06). Type class es allow additional capabilities to be added to a type: Sulzmann, Martin; Wang, Meng. Aspect-oriented programming with type classes . Proceedings of the 6th Workshop on Foundations of Aspect-oriented Languages. March 2007: 65–74. ISBN 978-1595936615 . S2CID 3253858 . doi:10.1145/1233833.1233842 . .
^ Numerous others: CaesarJ 互联网档案馆 的存檔 ,存档日期2008-12-19., Compose* Wikiwix的存檔 ,存档日期2005-08-21, Dynaop 互联网档案馆 的存檔 ,存档日期2007-07-24., JAC 互联网档案馆 的存檔 ,存档日期2004-06-19., Google Guice (as part of its functionality), Javassist 互联网档案馆 的存檔 ,存档日期2004-09-01., JAsCo (and AWED) 互联网档案馆 的存檔 ,存档日期2005-04-11., JAML 互联网档案馆 的存檔 ,存档日期2005-04-15., JBoss AOP 互联网档案馆 的存檔 ,存档日期2006-10-17., LogicAJ 互联网档案馆 的存檔 ,存档日期2006-05-04., Object Teams 互联网档案馆 的存檔 ,存档日期2005-08-31., PROSE 互联网档案馆 的存檔 ,存档日期2007-01-24., The AspectBench Compiler for AspectJ (abc) 互联网档案馆 的存檔 ,存档日期2014-12-16., Spring framework (as part of its functionality), Seasar , The JMangler Project 互联网档案馆 的存檔 ,存档日期2005-10-28., InjectJ 互联网档案馆 的存檔 ,存档日期2005-04-05., GluonJ 互联网档案馆 的存檔 ,存档日期2007-02-06., Steamloom 互联网档案馆 的存檔 ,存档日期2007-08-18.
^ Many: Advisable 互联网档案馆 的存檔 ,存档日期2008-07-04., Ajaxpect 互联网档案馆 的存檔 ,存档日期2016-07-09., jQuery AOP Plugin 互联网档案馆 的存檔 ,存档日期2008-01-13., Aspectes Wikiwix的存檔 ,存档日期2006-05-08, AspectJS 互联网档案馆 的存檔 ,存档日期2008-12-16., Cerny.js 互联网档案馆 的存檔 ,存档日期2007-06-27., Dojo Toolkit 互联网档案馆 的存檔 ,存档日期2006-02-21., Humax Web Framework 互联网档案馆 的存檔 ,存档日期2008-12-09., Joose 互联网档案馆 的存檔 ,存档日期2015-03-18., Prototype - Prototype Function#wrap 互联网档案馆 的存檔 ,存档日期2009-05-05., YUI 3 (Y.Do) 互联网档案馆 的存檔 ,存档日期2011-01-25.
^ Using built-in support for categories (which allows the encapsulation of aspect code) and event-driven programming (which allows the definition of before and after event handlers).
^ AspectLua . [11 August 2015] . (原始内容存档 于17 July 2015).
^ MAKAO, re(verse)-engineering build systems . [11 August 2015] . (原始内容 存档于24 July 2012).
^ McLab . [11 August 2015] . (原始内容存档 于24 September 2015).
^ AspectML - Aspect-oriented Functional Programming Language Research . [11 August 2015] . (原始内容存档 于5 December 2010).
^ Adam Kennedy. Aspect - Aspect-Oriented Programming (AOP) for Perl - metacpan.org . [11 August 2015] . (原始内容存档 于31 August 2013).
^ Several: PHP-AOP (AOP.io) Wikiwix的存檔 ,存档日期2014-08-18, Go! AOP framework 互联网档案馆 的存檔 ,存档日期2013-03-01., PHPaspect 互联网档案馆 的存檔 ,存档日期2016-08-22., Seasar.PHP 互联网档案馆 的存檔 ,存档日期2005-12-26., PHP-AOP , Flow 互联网档案馆 的存檔 ,存档日期2018-01-04., AOP PECL Extension 互联网档案馆 的存檔 ,存档日期2017-04-11.
^ bigzaphod.org is coming soon . www.bigzaphod.org. [5 May 2018] . (原始内容存档 于20 April 2016).
^ Several: PEAK 互联网档案馆 的存檔 ,存档日期2005-04-09., Aspyct AOP , Lightweight Python AOP 互联网档案馆 的存檔 ,存档日期2004-10-09., Logilab's aspect module 互联网档案馆 的存檔 ,存档日期2005-03-09., Pythius 互联网档案馆 的存檔 ,存档日期2005-04-08., Spring Python's AOP module 互联网档案馆 的存檔 ,存档日期2016-03-04., Pytilities' AOP module 互联网档案馆 的存檔 ,存档日期2011-08-25., aspectlib 互联网档案馆 的存檔 ,存档日期2014-11-05.
^ PLaneT Package Repository : PLaneT > dutchyn > aspectscheme.plt . [11 August 2015] . (原始内容存档 于5 September 2015).
^ AspectR - Simple aspect-oriented programming in Ruby . [11 August 2015] . (原始内容存档 于12 August 2015).
^ Dean Wampler. Home . [11 August 2015] . (原始内容 存档于26 October 2007).
^ gcao/aspector . GitHub. [11 August 2015] . (原始内容存档 于4 January 2015).
^ AspectS . tu-ilmenau.de. [5 May 2018] . (原始内容 存档于6 January 2006).
^ MetaclassTalk: Reflection and Meta-Programming in Smalltalk . [11 August 2015] . (原始内容 存档于29 July 2015).
^ WEAVR . iit.edu. [5 May 2018] . (原始内容存档 于12 December 2008).
^ aspectxml - An Aspect-Oriented XML Weaving Engine (AXLE) - Google Project Hosting . [11 August 2015] . (原始内容存档 于12 September 2015).
站外链接