1,AOP的思想
AOP: Aspect OrientedProgramming 面向切面编程。
面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是目前软件开发中的一个热点。AOP实际上是GoF(ObserverDesign Pattern)设计模式的延续,强调是调用者和被调用者之间的解耦,未开发者提供了一种描述横切关注点(Crosscutting Concern)的机制,并能够自动将横切关注点织入(weaving)到面向对象的软件系统中,从而实现了横切关注点的模块化,通过划分方面(Aspect)代码,横切关注点变得很容易处理。开发者可以在编译时更改,插入或除去系统的方面,甚至重用系统的切面[2]。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
在我们设计一个新系统时,首先需要关注的是如何处理那些主要的核心功能,对于商业应用来说也就是基本的业务逻辑。例如在一个银行应用系统中,核心模块用来处理储户使用的银行事务:在一个零售应用系统中,核心模块用来处理购买商品业务和库存管理业务。在这两个应用中,还存在一些全系统范围的共同关注点,例如日志记录、用户认证、数据持久性以及其他一些对很多核心业务模块来说共用的要素。这些分布在多个模块中的系统范围特性被称为横切关注点[5,6,7,9,10]。面向方面编程(AOP)就是处理这些横切关注点的。虽然面向对象编程(AOP)是当前处理核心关注点[5]最广泛的方法,但它对于横切关注点的处理还不够理想。典型的OOP所实现的核心关注点和横切关注点之间的耦合是不够理想的,如果要增加新的横切特性或者修改现存的横切功能,就必须对所有相关的核心模块进行修改,使得系统的维护和扩展变的异常困难,而导致这种现象的根本原因在于横切关注点在OOP中的实现方式都是分散在各个核心关注点内部的。
AOP是一种新技术,它的核心思想是将系统中的横切关注点和核心关注点分别模块化,其中横切关注点通过方面(aspect)实现模块化,核心关注点通过类(class)实现模块化,再通过一个类似于编译器的工具——切面编织器(Aspect weaver)[5~7] (也可以称为方面编译器)对已模块化的两类关注点进行编译,从而构造出新的系统。在传统的开发技术中并没有强调横切关注点这个概念,使得客观存在的横切需求被迫实现在核心需求的代码中,从而导致了代码的混乱和分散。因此,如何将横切关注点从核心需求模块中分离出来,成为面向切面技术首要的任务[10]。
2,AOP的基本概念
在面向对象编程(OOP)中,类,对象,封装,继承,多态等概念是描述面向对象思想主要术语。与此类似,在面向切面编程中,同样存在着一些基本概念。
2.2.1 关注点
关注点(concern):一个关注点可以是一个特定的问题,概念,或者是应用程序域,总而言之,应用程序必须达到的一个目标。关注点分为核心关注点和横切关注点。核心关注是有关业务逻辑,比如生成工资单,让员工记录,做银行转帐。横切关注点的定义见2.2.2横切关注点。2.2.2 横切关注点
横切关注点(Crosscutting Concerns):是一个关注点(concern)就是一个特定的目的,一块我们感兴趣的区域,从技术的角度来说,一个典型的软件系统可以映射成一些核心关注点和系统关注点。举例子来说,一个信用卡出来的系统的核心关注点是借贷/存入处理,而系统级的关注点则是日志,事务处理,授权,安全及其性能问题等,它们会在多个模块中出现,我们称其为横切关注点。横切关注点会在多个模块中出现。如果使用现有的编程方法,横切关注点会横越多个模块,结果是使系统难以设计、理解、实现和演进。AOP能够比上述方法更好地分离系统关注点,从而提供模块化的横切关注点。2.2.3 连接点
连接点(joint point):是在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候,关注点将在这里横切应用程序。连接点可以是方法调用、构造函数调用、异常处理程序、或者程序执行中的其他点。联结点是 AOP 的核心概念之一,它用来定义在程序的哪里通过 AOP 加入新的逻辑。在Spring AOP中,一个连接点总是表示一个方法的执行。2.2.4 切入点
切入点(Pointcut):一个切入点是用来定义某一个通知该何时执行的一组联结点。通过定义切入点,我们可以精确地控制程序中什么组件接到什么通知。上面我们提到,一个典型的连结点是方法调用,而一个典型的切入点就是对某一个类的所在方法调用的集合。通常我们会通过组建复杂的切入点来控制通知什么时候被执行。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。2.2.5 通知
通知(advice):通知作为AOP语言的主要程序结构之一, 通常与某个切入点相关联,用来描述在相应连接点处所需调用的程序逻辑,其结构类似于OOP中的方法(method)。实际上,在很多AOP语言中就是把通知作为方法来进行存储和调用的。不同之处主要在于:调用方法时需要将其调用语句显式地写在基础程序中;而调用通知则体现了AOP中所强调的好莱坞法则(Hollywood princple不需要在基础程序的代码中显式调用通知,其调用逻辑会被织入机制自动插入到基础程序的执行流程中。这种方式使开发人员在编写基础程序时不需要考虑通知的存在,可以更加专注于业务逻辑[14] 。基本通知的种类如下:
前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
后置通知(After returning advice):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
异常通知(After throwing advice):在方法抛出异常退出时执行的通知。
最终通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。
2.2.6 切面
切面(Aspect,也译作方面):一个关注点的模块化,这个关注点可能会横切多个对象,其地位就相当于OOP中的类,它将通知,连接点以及类型间声明的一个组合。同类相似,方面也可以有自己的成员函数和变量,从其他类或者方面扩展以及实现接口等。与类不同的是方面的构造是由AOP框架来构造的,不能像类一样使用new关键字来显式生成实例[11]。切面从抽象意义上讲,是对系统组件的性能和语法产生一定影响的一些属性[12];从设计上讲,是横切系统的一些软件系统关注点;从实现上讲.切面是一种程序构造单元。它支持将横切系统的关注点封装到单独的模块单位中[13],典型的切面如异常处理,日志处理,安全验证和事务处理等模块。
2.2.7 目标
目标(target):目标是一个被切入的地方,它一般是核心关注点,业务功能。例如2.2.2横切关注点中举例的信用卡系统的核心关注点是借贷/存入处理就是目标。2.2.8 目标对象
目标对象(Target Object):被一个或者多个切面所通知的对象。也被称做被通知(advised)对象,也即被织入横切关注点的对象,即该对象是切入点选择的对象。它在执行过程中会受到某一个AOP的修改,例如在 Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。2.2.9 编织
编织(Weaving,又译为织入):组装切面创建通知化对象[2]。织入是将切面真正加入程序代码的过程。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其它纯Java AOP框架一样,运行时完成织入。
3,横切
横切是AOP的关键技术,也就是AOP的核心。这也是正式AOP和OOP差别之所在,一个系统按照00P的视角可以按照功能“纵向”分割为一个个的对象(如继承)。而AOP则从“横向”的角度将系统的一部分分割为一个个方面。“横切”是AOP的专有名词。它是一种蕴含强大力量的相对简单的设计和编程技术。尤其是用于建立松散耦合的、可扩展的企业系统时。横切可以使得AOP在一个给定的编程模型中穿越既定的职责部分的操作。如果不使用横切技术。软件开发是怎样的情形呢?在传统的程序中,由于横切行为的实现是分散的。开发人员很难对这些行为进行逻辑上的实现或更改。例如.用于日志记录的代码和主要用于其它职责的代码缠绕在一起。根据所解决的问题的复杂程度和作用域的不同。所引起的混乱可大可小。更改一个应用程序的日志记录策略可能涉及数百次编辑——即使可行。这也是个令人头疼的任务[15]。
4,关注点识别
通过对系统需求和实现的识别,我们可以将模块中的这些关注点分为:核心关注点和横切关注点。对于核心关注点而言,通常来说,实现这些关注点的模块是相互独立的,他们分别完成了系统需要的商业逻辑,这些逻辑与具体的业务需求有关。而对于日志、安全、持久化等关注点而言,他们却是商业逻辑模块所共同需要的,这些逻辑分布于核心关注点的各处。在AOP中,诸如这些模块,都称为横切关注点。应用AOP的横切技术,关键就是要实现对关注点的识别。
如果将整个模块比喻为一个圆柱体,那么关注点识别过程可以用三棱镜法则来形容,穿越三棱镜的光束(指需求),照射到圆柱体各处,获得不同颜色的光束,最后识别出不同的关注点。如图2.2 关注点识别-三菱镜法则5,将横切关注点编织到核心关注点中
AOP的目的,就是要将诸如Logging之类的横切关注点从BusinessLogic类中分离出来。利用AOP技术,可以对相关的横切关注点封装,形成单独的切面。这就保证了横切关注点的复用。由于BusinessLogic类中不再包含横切关注点的逻辑代码,为达到调用横切关注点的目的,可以利用横切技术,截取BusinessLogic类中相关方法的消息,例如SomeOperation()方法,然后将这些切面编织到该方法中。将横切关注点编织到核心关注点中,如图2.3 AOP模型通过利用AOP技术,改变了整个系统的设计方式。在分析系统需求之初,利用AOP的思想,分离出核心关注点和横切关注点。在实现了诸如日志、事务管理、权限控制等横切关注点的通用逻辑后,开发人员就可以专注于核心关注点,将精力投入到解决企业的商业逻辑上来。同时,这些封装好了的横切关注点提供的功能,可以最大限度地复用于商业逻辑的各个部分,既不需要开发人员作特殊的编码,也不会因为修改横切关注点的功能而影响具体的业务功能。
AOP技术应用和研究系列博客 AOP技术应用和研究