`
junli0411
  • 浏览: 136186 次
  • 来自: ...
社区版块
存档分类
最新评论
阅读更多

<o:p></o:p>

向对象技术很好地解决了软件系统中角色划分的问题。借助于面向对象的分析、设计和实现技术,开发者可以将问题领域的名词转换成软件系统中的对象,从而很自
  
然地完成从问题到软件的转换.
  
但是,问题领域的某些需求却偏偏不是用这样的名词来描述的.我的一个朋友就曾经遇到这样的问题:需要对系统中的某些方法进行日志记录,这种需要记录方法
  
散布在40多个类中。面对这种需求,应该怎么办呢?最直接的办法就是:创建一个起类(或接口),将日志的功能放在其中,并让所有需要日志功能的类继承这个起类(或接口).如果这个需求是后期提出的.需要修改的地方就会分散在40多个文件(如果是C+十,这个数量还可能加倍)中。这样大的修改量,无疑会增加出错的几率,并且加大系统维护的难度。
  
人们认识到,传统的程序经常表现出一些不能自然地适合单个程序模块或者几个紧密相关的程序模块的行为 例如日志记录、对上下文敏感的错误处理、性能优化以及设计模
  
式等等、我们将这种行为称为横切关注点(crosscuttingconcern,因为它跨越了给定编程模型中的典型职责界限。如果使用过用于核切关注点的代码,您就会知道缺乏模块性所带来的问日。因为横切行为的实现是分散的,开发人员发现这种行为难以作逻辑思维、实现和更改.
  
因此,面向方面的编程(AspectOrientedProgrammingAOP)应运而生。AOP为开发者提供了一种描述横切关注点的机制,并能够自动将横切关注点织入到面向对象的软件系统中,从而实现了横切关注点的模块化.通过划分Aspect代码,横切关注点变得容易处理。开发者可以在编译时更改、插入或除去系统的Aspect,甚至重用系统的Aspect
  
更重要的是,AOP可能对软件开发的过程造成根本性的影响。我们可以想象这样一种情况:OOP只用于表示对象之间的泛化一特化(generalizationspecialization)关系(通过继承来表现),而对象之间的校向关联则完全用AOP来表现。这样,很多给对象之间横向关联增加灵活性的设计模式(例如DecoratorRole Object等)将不再必要.
  
一种编程思想是否真正优秀,只有从实现语言上才能看到。施乐公司帕洛阿尔托研究中心(Xerox PARC)开发了第一个AOP的开发环境——AsPectJ ,这个工具提供了一整套的语法,能够清楚地描述横切关注点,并将其织入到Java源代码中。织入后的代码仍是标准Java代码,因此AspectJ不会影响Java的移植能力。此外,AspectJ提供了一个独立的IDE,并且能够嵌入到JbuilderForteJava开发环境之中,无缝地提供AOP的能力。关于AspectJ,读者可以在http//www.aspectj.org找到更多的信息。
  
但是,现在的AOP还处于相当不完善的阶段:它只能应用于很少的几种语言环境下,并且必须掌握源代码才能进行织入.但以RUP之父Ivar Jacobson为代表的科学家们仍对AOP推崇备至:他认为AOP将最终改变整个软件开发的方式,并且更完美地实现用例驱动的开发思想.
  
  
 
  
  
利用AOP分离软件关注点
  
  
一个关注点(concern)就是一个特定的目的,一块我们感兴趣的区域。从技术的角度来说,一个典型的软件系统包含一些核心的关注点和系统级的关注点。举个例子来说,一个信用卡处理系统的核心关注点是借贷/存入处理,而系统级的关注点则是日志、事务完整性、授权、安全及性能问题等,许多关注点——我们叫它横切关注点(crosscutting concerns——会在多个模块中出现,使用现有的编程方法,横切关注点会横越多个模块,结果是使系统难以设计、理解、实现和演进。
  AOP
能够比上述方法更好地分离系统关注点,从而提供模块化的横切关注点。
  
在这篇文章里,我首先会解释横切关注点在软件系统中引起的问题,接着我会介绍AOP是怎样解决横切关注点问题的。
  
软件编程方法的演进
  
在计算机科学的早期阶段,开发人员使用简单的机器级代码来编程。不幸的是,程序员得花费更多时间来考虑一种特定机器的指令集而不是手中需要解决的问题本身。慢慢地,我们转而使用允许对底层机器做某种抽象的高级语言。然后是结构化语言,我们可以把问题分解成一些必要的过程来完成任务。但是,随着复杂程度的增加,我们又需要更适合的技术。面向对象的编程方式(OOP)使我们可以把系统看作是一批相互合作的对象。类允许我们把实现细节隐藏在接口下。多态性为相关概念提供公共的行为和接口,并允许特定的组件在无需访问基础实现的前提下改变特定行为。
  
编程方法和语言决定了我们和计算机交流的方式。每一种新的方法学都提出一种新的分解问题的方法:机器码、伪代码、过程和类等。每种新的方法学都使得从系统需求到编程概念的映射更加自然。编程方法学的发展让我们可以建立更加复杂的系统,这名话反过来说也地,我们能够建立更加复杂的系统是加为这些技术允许我们处理这种复杂度。
  
现在,大多数软件项目都选择OOP的编程方式。确实,OOP已经表明了它处理一般行为的能力,但是,我们将会看到(或许你已经感觉到了):OOP不能很好地处理横越多个——经常是不相关的——模块的行为。相比之下,AOP填补了这个空白,它很可能会是编程方法学发展的一个里程碑。
  
把系统看作一批关注点
  
我们可以把一个复杂的系统看作是由多个关注点来组合实现的。一个典型的系统可能会包括几个方面的关注点,如业务逻辑、性能,数据存储、日志和调度信息、授权、安全、线程、错误检查等,还有开发过程中的关注点,如易懂、易维护、易追查、易扩展等,图1演示了由不同模块实现的一批关注点组成一个系统。
  <v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype><v:shape id="_x0000_i1026" style="WIDTH: 453.75pt; HEIGHT: 339.75pt" type="#_x0000_t75" alt=""><v:imagedata src="file:///C:\DOCUME~1\slj\LOCALS~1\Temp\msohtml1\01\clip_image001.jpg" o:href="http://www.sawin.cn/doc/share/2142086.jpg"></v:imagedata></v:shape>
  
2把需求比作一束穿过三棱镜的光。我们让需求之光通过鉴别关注点的三棱镜,就会区别出每个关注点。
  <v:shape id="_x0000_i1027" style="WIDTH: 487.5pt; HEIGHT: 260.25pt" type="#_x0000_t75" alt=""> <v:imagedata src="file:///C:\DOCUME~1\slj\LOCALS~1\Temp\msohtml1\01\clip_image002.jpg" o:href="http://www.sawin.cn/doc/share/2142010.jpg"></v:imagedata></v:shape>
  
开发人员建立一个系统以满足多个需求,我们可以大致地把这些需求分类为核心模块级需求和系统组需求。很多系统级需求一般来说是相互独立的,但它们一般都会横切许多核心模块。举个例子来说,一个典型的企业应用包含许多横切关注点,如验证、日志、资源地、系统管理、性能及存储管理等,每一个关注点都牵涉到几个子系统,如存储管理关注点会影响到所有的有状态业务对象。
  
让我们来看一个简单的例子,考虑一个封装了业务逻辑的类的实现框架:
  public class SomeBusinessClass extends
  otherBusinessClass{
  //
核心数据成员
  //
其它数据成员:日志流,保证数据完整性的标志位等
  //
重载基类的方法
  public void performSomeOperation
  (OperationInformation info)
  //
安全性验证
  //
检查传入数据是否满足协议
  //
锁定对象以食品店当其他线程访问时的数据完整性
  //
检查缓存中是否为最新信息
  //
记录操作开始执行时间
  //
执行核心操作
  //
记录操作完成时间
  //
给对象解锁
  }
  //
一些类似操作
  public void save(PersitanceStorage ps){
  }
  public void save(PersitanceStorage ps){
  }
  }
  
在上面的代码中,我们注意到三个问题:首先,其它数据成员不是这个类的核心关注点;第二performSomeOperation()的实现做了许多核心操作之外的事,它要处理日志、验证、线程安全、协议验证和缓存管理等一些外围操作,而且这些外围操作同样也会应用于其他类;第三,save()和load()执行的持久化操作是否构成这个类的核心是不清楚的.
  
横切关注点的问题
  
虽然横切关注点会跨越多个模块,但当前的技术倾向于使用一维的方法学来处理这种需求,把对应需求的实现强行限制在一维的空间里.这个一维空间就是核心模块级实现.其他需求的实现被嵌入在这个占统治地位的空间.换句话说,需求空间是一个n维空间,而实现空间是一维空间,这种不匹配导致了糟糕的需求到实现的映射。
  
表现
  
用当前方法学实现横切关注点是不好的.它会带来一些问题,我们可以大致把这些问题分为两类。
  
代码混乱:软件系统中的模块可能要同时兼顾几个方面的需要.举例来说,开发者经常要同时考虑业务逻辑、性能、同步,日志和安全等问题,兼顾各方面的需要导致相应关注点的实现元素同时出现,引起代码混乱.
  
代码分散:由于横切关注点本来就涉及到多个模块.相关实现也就得遍布在这些模块里.如在一个使用了数据库的系统里,性能问题就会影响所有访问数据库的模块。这导致代码分散在各处.
  
结果
  
混乱和分散的代码会从多个方面影响系统的设计和开发:
  
可读性差:同时实现几个关注点模糊了不同关注点的实现,使得关注点与其实现之间的对应关系不明显。
  
低产出:同时实现几个关注点把开发人员的注意移到外围关注点,导致生产效率降低.
  
低代码重用率: 由于一个模块实现多个关注点,因此其他需要类似功能的系统不能马上使用该模块.进一步降低了生产效率。
  
代码质量差:混乱的代码掩盖了代码中隐藏的问题。而且,由于同时要处理多个关注点.应该特别注意的关注点得不到应有的关注.
  
难以扩展:狭窄的视角和有限的资源总是产生仅注意当前关注点的设计.新的需求导致从新实现.由于实现不是模块化的,就是说实现牵涉到多个模块,为了新需求修改子系统可能会带来数据的不一致,而且还需相当规模同测试来保证这些修改不会带来bug
  
当前解决方法
  
由于多数系统中都包含横切关注点、自然的已经形成了一些技术来模块化横切关注点的实现,这些技术包括:混入类、设计模式和面向特定问题域的解决方式。
  
使用混入类,你可以推迟关注点的最终实现.基本类包含一个混入类的实例,允许系统的其他部分设置这个实例。举个例子来说,实现业务逻辑的类包含一个混入的logger,系统的其他部分可以设置这个logger已得到合适的日志类型,比如logger可能被设置为使用文件系统或是消息中间件。在这种方式下,虽然日志的具体实现被推迟,基本类还是必须在所有写日志的点调用日志操作和控制日志信息的代码。
  
行为型设计模式,如VisitorTemplate Method模式,也允许你推迟具体实现。但是也就像混入类一样,操作的控制——调用visitortemplate Method的逻辑——仍然留给了基本类。
  
面向特定问题域的解决方式,如框架和应用服务器,允许开发者用更模块化的方式处理某些横切关注点。比如E J BEnterprise JavaBean)架构,可以处理安全、系统管理、性能和容器管理的持久化(container-managed persistence)等横切关注点。B e a n与数据库的映射,但是大多数情况下,开发者还是要了解存储结构。这种方式下,你用基于XML的映射关系描述器来实现于数据持久化相关的横切关注点。
  
面向特定问题域的解决方式提供了解决特定问题的专门机制,它的缺点是对于每一种这样的解决方式开发人员都必须重新学习,另外,由于这种方式是特定问题域相关的,属于特定问题域之外的横切关注点需要特殊的对待。
  

分享到:
评论

相关推荐

    ioc AOP深入了解

    ioc 及aop 使用基础 与spring结合

    Spring AOP实验

    1、了解AOP的概念和作用; 2、理解AOP中的相关术语; 3、了解Spring中两种动态代理方式的区别; 4、掌握基于XML和注解的AspectJ开发。 二、 实验内容 1、按图所示的类图结构,设计接口及其实现类,并完成另外两附加...

    你真的了解AOP? 解读Spring Aop 官方文档(附视频)-附件资源

    你真的了解AOP? 解读Spring Aop 官方文档(附视频)-附件资源

    aopalliance-white-paper(AOP Alliance白皮书)

    aopallice白皮书,文章描述了AOP Alliance工程的相关情况,对于了解AOP Alliance很有帮助。文章是e文的。

    AOP练习小例子

    这是AOP练习的小例子,结合了容器和用C#反射发出实现了动态代理,用来了解AOP基本原理

    spring第四天.pdf

    2. 了解AOP能干什么? 3. 了解AOP都有哪些实现? 4. 掌握AOP核心概念(通知、切入点、切面、代理对象、目标对象、织入等) 5. 了解切入点表达式 6. 了解通知类型(五种) 7. 重点掌握aop底层的原理之动态代理机制的...

    AOP 的相关概念[理解].md

    了解SpringAOP相关概念,了解AOP在程序中的优势,Spring 框架监控切入点方法的执行。一旦监控到切入点方法被运行,使用代理机制,动态创建目标对 象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的...

    Aop例子 demo

    近来因为工作需要,开始研究Aop,上面是一个简单的示例程序,看了就能了解aop的原理。 比spring aop简单很多。 希望对初学者有帮助,

    spring_教程_2_AOP

    简介AOP知识,包括概念,了解AOP 撑握理解AOP术语 理解Spring中AOP的实现 撑握通知、切入点的定义与使用 撑握ProxyFactoryBean的使用 撑握Spring自动代理的使用

    AspectJ Cookbook中文版

    许多开发人员都对aop感兴趣 —— 特别是对aspectj感兴趣,这个java编程语言的开源...如果想了解aop如何改变软件开发的方式,如何使用aspectj使代码更加模块化,更易于开发、维护、演进和部署,那么本书确实很适合你。

    用Java动态代理实现AOP

    目前整个开发社区对AOP(Aspect Oriented Programing)推崇备至,也涌现出大量支持AOP的优秀... 要详细了解学习AOP可以到它老家http://aosd.net去瞧瞧。这里只是意图通过一个简单的例子向初学者展示一下如何来进行AOP。

    Java应用开发实验二.docx

    1、了解AOP的概念和作用; 2、理解AOP中的相关术语; 3、了解Spring中两种动态代理方式的区别; 4、掌握基于XML和注解的AspectJ开发。 二、实验内容 1、按图所示的类图结构,设计接口及其实现类,并完成另外两附加...

    Spring之AOP介绍

    对Spring框架中的AOP的介绍,能够全面了解Spring中AOP的功能和使用方法。

    以注解方式模拟Spring IoC AOP

    以注解方式模拟Spring IoC AOP,了解Spring是如何实现的.

    SPRING AOP详细培训视频

    SPRING AOP详细培训视频,通过本视频可以对AOP的通知、代理、引入做详细了解和学习

    Spring AOP 类图

    Spring AOP 类图,通用了解Spring AOP实现,AOP代理自动生成。

Global site tag (gtag.js) - Google Analytics