`
阅读更多
先来看一个实际开发中的例子,我们常常需要对系统中的某些方法进行日志记录,需要日志记录的方法常常散布在几十个类中。面对这种需求,传统方法就是创建一个基类(或接口),将日志的功能放在其中,并让所有需要日志功能的类继承这个基类(或接口)。

如果这个需求是后期提出的。需要修改的地方就会分散在几十个文件。这样大的修改量,无疑会增加出错的几率,并且加大系统维护的难度。
  
人们认识到,OOP程序设计经常表现出一些不能自然地适合单个程序模块或者几个紧密相关的程序模块的行为:例如日志记录、对上下文敏感的错误处理、性能优化以及设计模式等等,我们将这种行为称为“横切关注点(cross cutting concern)”,因为它跨越了给定编程模型中的典型职责界限。

一个关注点(concern)就是一个特定的目的,一块我们感兴趣的区域。从技术的角度来说,一个典型的软件系统包含一些核心的关注点和系统级的关注点。开发人员建立一个系统以满足多个需求,我们可以大致地把这些需求分类为核心模块级需求和系统组需求。很多系统级需求一般来说是相互独立的,但它们一般都会横切许多核心模块。一个典型的企业应用包含许多横切关注点,如验证、日志、资源池、系统管理、性能及存储管理等,每一个关注点都牵涉到几个子系统,如存储管理关注点会影响到所有的有状态业务对象。举个例子来说,一个信用卡处理系统的核心关注点是借贷/存入处理,而系统级的关注点则是日志、事务完整性、授权、安全及性能问题等,使用现有的编程方法,横切关注点会横越多个模块,结果是使系统难以设计、理解、实现和演进。



这是一个封装了业务逻辑的类的实现框架:

  public class SomeBusinessClass extends   otherBusinessClass
{   
//核心资料成员   
//其它资料成员:日志流,保证资料完整性的标志位等   
//重载基类的方法   
public void performSomeOperation   (OperationInformation info)   { 
//安全性验证   
//检查传入资料是否满足协议   
//锁定对象以食品店当其它线程访问时的资料完整性   
//检查缓存中是否为最新信息   
//记录操作开始执行时间   
//执行核心操作   
//记录操作完成时间   
//给对象解锁   
} 
//一些类似操作   
public void save(PersitanceStorage ps){   }  
public void load(PersitanceStorage ps){   }
 }



在上面的代码中,我们注意到三个问题:首先,其它资料成员不是这个类的核心关注点;第二、performSomeOperation()的实现做了许多核心操作之外的事,它要处理日志、验证、线程安全、协议验证和缓存管理等一些外围操作,而且这些外围操作同样也会应用于其它类;第三,save()和load()执行的持久化操作是否构成这个类的核心是不清楚的。

由于多数系统中都包含横切关注点、自然的已经形成了一些技术来模块化横切关注点的实现,这些技术包括:混入类、设计模式和面向特定问题域的解决方式。

使用混入类,你可以推迟关注点的最终实现.基本类包含一个混入类的实例,允许系统的其它部分设置这个实例。举个例子来说,实现业务逻辑的类包含一个混入的logger,系统的其它部分可以设置这个logger已得到合适的日志类型,比如logger可能被设置为使用文件系统或是消息中间件。在这种方式下,虽然日志的具体实现被推迟,基本类还是必须在所有写日志的点调用日志操作和控制日志信息的代码。

行为型设计模式,如Visitor和Template Method模式,也允许你推迟具体实现。但是也就像混入类一样,操作的控制——调用visitor或template Method的逻辑——仍然留给了基本类。 

面向特定问题域的解决方式,如框架和应用服务器,允许开发者用更模块化的方式处理某些横切关注点。比如E J B(Enterprise JavaBean)架构,可以处理安全、系统管理、性能和容器管理的持久化(container-managed persistence)等横切关注点。B e a n与数据库的映像,但是大多数情况下,开发者还是要了解存储结构。这种方式下,你用基于XML的映像关系描述器来实现于资料持久化相关的横切关注点。它的缺点是对于每一种这样的解决方式开发人员都必须重新学习,另外,由于这种方式是特定问题域相关的,属于特定问题域之外的横切关注点需要特殊的对待。

设计师的两难局面 

好的系统设计师不仅会考虑当前需求,还会考虑到可能会有的需求以避免到处打补丁。这样就存在一个问题预知将来是很困难的,如果你漏过了将来可能会有的横切关注点的需求,你将会需要修改或甚至是重新实现系统的许多部分;从另一个角度来说,太过于关注不一定需要的需求会导致过分设计的、难以理解的、臃肿的系统。所以系统设计师处在这么一个两难局面中:怎么设计算不了过分设计?应该宁可设计不足还是宁可过分设计?

举个例子来说,设计师是否应该在系统中包含现在并不需要的日志机制?如果是的话,哪里是应该写日志的点?日志应该记录那些信息相似的例子还有关于性能的优化问题,我们很少能预知瓶颈的所在。常用的方法是建立系统,profile它,然后翻新系统以提高性能,这种方式可能会依照profiling而修改系统的很多部分。此外,随着时间的流逝,由于使用方式的变化,可能还会产生新的瓶颈。类库设计师的任务更困难,因为他很难设想出所有对类库的使用方式。

总而言之,设计师很难顾及到系统可能需要处理的所有关注点。即使是在已经知道了需求的前提下,某些建立系统时需要的细节 也可能不能全部得到,整体设计就面临着设计不足/过分设计的两难局面。

利用AOP分离软件关注点 

AOP, 从其本质上讲,使你可以用一种松散耦合的方式来实现独立的关注点,然后 组合这些实现来建立最终系统、用它所建立的系统是使用松散偶合的,模块化实现的横切关注点来搭建的、与之对照 用OOP建立的系统则是用松散耦合的模块化实现的一般关注点来实现的。在AOP中,这些模块化单元叫“方面(aspect)”,而在OOP中,这些一般关注点的实现单元叫做类。

AOP为开发者提供了一种描述横切关注点的机制,并能够自动将横切关注点织入到面向对象的软件系统中,从而实现了横切关注点的模块化.通过划分Aspect代码,横切关注点变得容易处理。开发者可以在编译时更改、插入或除去系统的Aspect,甚至重用系统的Aspect。

更重要的是,AOP可能对软件开发的过程造成根本性的影响。我们可以想象这样一种情况:OOP只用于表示对象之间的泛化一特化(generalization-specialization)关系(通过继承来表现),而对象之间的横向关联则完全用AOP来表现。这样,很多给对象之间横向关联增加灵活性的设计模式(例如Decorator、Role Object等)将不再必要。

AOP 包括三个清晰的开发步骤:

方面分解:分解需求撮出横切关注点。在这一步里,你把核心模块级关注点和系统级的横切关注点分离开来、就前面所提到的信用卡例子来说 你可以分解出三个关注点:核心的信用卡处理、日志和验证。

关注点实现:各自独立的实现这些关注点,还用上面信用卡的例子,你要实现信用卡处理单元、日志单元和验证单元。 

方面的重新组合:在这一步里,方面集成器通过创建一个模块单元—一方面来指定重组的规则, 重组过程—一也叫织入(weaving)或结合(integrating)——则使用这些信息来构建最终系统、还拿信用卡的那个例子来说 你可以指定(用某种AOP的实现所提供的语言)每个操作的开始和结束需要记录,并且每个操作在涉及到业务逻辑之前必须通过验证。
 


AOP与OOP最重要的不同在于它处理横切关注点的方式.在AOP中 每个关注点的实现都不知道其它关注点是否会“关注”它,如信用卡处理模块并不知道其它的关注点实现正在为它做日志和验证操作。它展示了一个从OOP转化来的强大的开发范型。

注意:一个AOP实现可以借助其它编程范型作为它的基础,从而原封不动的保留其基础范型的优点。例如,AOP可以选择OOP作为它的基础范型,从而把OOP善于处理一股关注点的好处直接带过来。用这样一种实现,独立的一般关注点可以使用OOP技术、这就像过程型语言是许多OOP语言的基础一样。 

AOP语言剖析 

就像其它编程范型的实现一样,AOP的实现由两部分组成:语言规范和实现。语言规范描述了语言的基础单元和语法;语言实现则按照语言规范来验证代码的正确性,并把代码转成目标机器可执行的形式。

AOP语言规范 

从抽象的角度看来 一种AOP语言要说明下面两个方面:

关注点的实现:把每个需求映像为代码,然后,编译器把它翻译成可执行代码。由于关注点的实现以指定过程的形式出现,你可以使用传统语言如C、C++、JAVA等。

织入规则规范:怎样把独立实现的关注点组合起来形成最终系统呢?为了这个目的 需要建立一种语言来指定组合不同的实现单元,以形成最终系统的规则。这种指定织入规则的语言可以是实现语言的扩展,也可以是一种完全不同的语言。 

AOP语言的实现 

AOP的编译器执行两步操作:
1、 组装关注点
2、组装结果转成可执行代码。
 
AOP实现可以用多种方式实现织入, 包括源码到源码的转换、它预处理每个方面的源码,产生织入过的源码,然后把织入过的源码交给基础语言的编译器, 产生最终可执行代码。比如 使用这种方式,一个基于Java的AOP实现可以先把不同的方面转化成Java源代码,然后让Java编译器把它转化成字节码.也可以直接在字节码级别执行织入; 毕竟 字节码本身也是一种源码。此外,底层的执行系统—一Java虚拟机—一也可以设计为支持AOP的。基于Java的AOP实现如果使用这种方式的话,虚拟机可以先装入织入规则,然后对后来装入的类都应用这种规则、也就是说,它可以执行just-in-time的方面织入。 

AOP的好处 

AOP可帮助我们解决上面提到的代码混乱和代码分散所带来的问题,它还有一些别的好处: 

模块化横切关注点:AOP用最小的耦合处理每个关注点,使得即使是横切关注点也是模块化的。这样的实现产生的系统,其代码的冗余小。模块化的实现还使得系统容易理解和维护。 

系统容易扩展:由于方面模块根本不知道横切关注点,所以很容易通过建立新的方面加入新的功能.另外,当你往系统中加入新的模块时,已有的方面自动横切进来,使系统易于扩展。 

设计决定的迟绑定:还记得设计师的两难局面吗?使用AOP 设计师可以推迟为将来的需求作决定,因为他可以把这种需求作为独立的方面很容易地实现。 

更好的代码重用性:AOP把每个方面实现为独立的模块, 模块之间是松散耦合的.举例来说,你可以用另外一个独立的日志写入器方面来替换当前的,用于把日志写入数据库,以满足不同的日志写入要求。松散藕合的实现通常意味着更好的代码重用性,AOP在使系统实现松散出合这一点上比OOP做得更好。 

AspectJ:一个Java的AOP实现 

AspectJ是一个可免费获得的、由施乐公司帕洛阿尔托研究中心(Xerox PARC)开发的、Java的AOP实现。它使用java作为单个关注点的实现语言,并扩展Java以指定织入规则。

另外,AspectJ允许以多种方式用方面和类建立新的方面,你可以引入新的资料成员和方法或是声明一个新的类来继承和实现另外的类或接口。 

AspectJ的织入器——AspectJ的编译器——负责把不同的方面组合在一起,由于AspectJ编译器建立的最终系统是Java字节码,因此,它可以运行在任何符合Java标准的虚拟机上。而且,AspectJ还提供了一些工具,例如调试器和Java IDE集成等。 

我需要AOP吗? 

AOP仅仅是解决设计上的缺点吗?在AOP里,每个关注点的实现的并不知道是否有其它关注点关注它,这是AOP和OOP的主要区别。在AOP里,组合的流向是从横切关注点到主关注点,而OOP则相反。但是,OOP可以和AOP很好地共存。比如,你可以使用一个混入类来做组合,既可以用AOP实现,也可以用OOP实现,这取决你对AOP的接受程度,在这两种情况下,实现横切关注点的混入类实现都无需知道它自己是被用在类中还是被用在方面中。举个例子来说,你可以把一个日志写入器接口用作某些类的混入类或是用作一个日志方面,因而,从OOP到AOP 是渐进的。
  
如果你的系统中涉及到多个横切关注点,你可以考虑进一步了解AOP,了解它的实现和它的好处。AOP很可能会是编程方式的一个里程碑。
分享到:
评论

相关推荐

    深入理解Android之AOP

    面向切面编程(AOP)是软件开发领域的一项重要技术,它与面向对象编程(OOP)相对应,但关注点不同。在本篇中,我们将深入探讨AOP的基本概念、优势以及在Android开发中的应用,同时与OOP进行比较分析。 首先,面向...

    Spring AOP基础关于AOP是什么的理解

    Spring 中的 AOP 只有完整 AOP 功能中的一部分,Spring 的设计目标之一就是不提供全部 AOP 功能,而是提供最常用的 AOP 的功能。因此 Spring 的 AOP 非常简单易用。如果需要额外的 AOP 支持,则可采用 AspectJ。 ...

    Spring之AOP介绍

    ### Spring之AOP介绍 #### 一、AOP概述 面向方面编程(Aspect-Oriented Programming,简称AOP)作为一种编程范式,旨在通过模块化的方式处理横切关注点(Cross-cutting Concerns)。传统的面向对象编程(OOP)虽然...

    aopalliance-1.0

    1. `MethodInterceptor` 接口:这是AOP Alliance的核心接口之一,代表了一个方法拦截器。在AOP中,拦截器允许我们在方法调用前后插入自定义的行为。通过实现这个接口,开发者可以创建自己的拦截逻辑,例如日志记录、...

    仿springAOP框架

    在Java开发领域,Spring框架以其强大的功能和灵活性深受开发者喜爱,其中AOP(面向切面编程)是其核心特性之一。AOP允许开发者将关注点从主业务逻辑中分离出来,如日志记录、事务管理等,实现代码的模块化和可复用性...

    Spring AOP 概念理解及@AspectJ支持

    **Spring AOP 概念理解** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的一个重要组成部分,它允许我们通过...理解和熟练运用Spring AOP及其@AspectJ注解是每个Spring开发者必备的技能之一。

    aopalliance-1.0.rar

    1. `MethodInterceptor`: 这是AOP Alliance的核心接口之一,它定义了拦截器的行为。拦截器允许我们在方法调用前后插入自定义逻辑,例如日志记录、性能监控、事务管理等。通过实现这个接口,开发者可以创建自己的拦截...

    Spring AOP面向方面编程原理:AOP概念

    Spring框架作为Java开发领域的领头羊之一,提供了强大的AOP支持。本文旨在深入探讨Spring AOP的核心概念及其原理。 #### 二、AOP基本概念 AOP是一种编程范式,其目的是提高模块化程度,特别是将那些对很多类都具有...

    aop介绍

    使用 AOP 可以让我们从一个更高的抽象概念来理解软件系统,AOP 也许提供一种有价值的工具。可以这么说:因为使用 AOP 结构,现在 JBoss 4.0 的源码变得更加简洁、易维护、易扩展。 AOP 的优点 AOP 的优点包括: * ...

    Spring AOP完整例子

    Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许开发者在不修改源代码的情况下,通过插入切面来增强或改变程序的行为。在本教程中,我们将深入探讨Spring AOP的不同使用方法,包括定义切点、通知类型...

    spring-aop-jar

    "spring-aop-jar"这个主题涉及到Spring框架中的核心组件之一——Spring AOP。这里我们将深入探讨Spring AOP、相关jar文件以及它们在实际开发中的作用。 首先,我们来看一下提供的文件: 1. aopalliance.jar:这是一...

    死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序.pdf

    Spring AOP 是一种面向切面编程的技术,它允许我们在不修改源代码的情况下,对应用程序的特定部分(如方法调用)进行增强。在 Spring 中,AOP 的实现主要依赖于代理模式,有两种代理方式:JDK 动态代理和 CGLIB 动态...

    aopalliance-1.0.jar下载

    而aopalliance-1.0.jar是实现这一目标的关键组件之一。这个库是AOP联盟(AOP Alliance)的一个产品,它提供了一组公共接口,使得不同的AOP框架可以互相协作,从而在各种AOP实现之间保持兼容性。 AOP联盟是一个开源...

    aopalliance.jar

    在Java开发领域,Spring框架无疑是最为广泛使用的轻量级框架之一。在Spring 3.0版本中,aopalliance.jar扮演了至关重要的角色。本文将深入探讨aopalliance.jar与Spring 3.0的关系,以及它在面向切面编程(AOP)中的...

    Spring之AOP配置文件详解

    其中,面向切面编程(Aspect Oriented Programming,简称AOP)是Spring框架的重要组成部分之一。通过AOP,开发者可以将那些横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,使得业务代码更加简洁、可...

    aop@work.rar

    《面向切面编程(AOP)的工作原理与实践》 面向切面编程(Aspect-Oriented Programming,简称AOP)是软件...了解并掌握AOP的原理和实践,有助于提升软件设计的灵活性和可维护性,是现代企业级应用开发的重要技能之一。

    Spring之AOP注解之引入通知

    在Spring框架中,AOP(面向切面编程)是一种强大的工具,它允许程序员将关注点分离,例如日志记录、事务管理等,从核心业务逻辑中解耦出来。本篇文章将深入探讨Spring AOP中的注解引入通知,以及如何利用它们来增强...

    开源框架spring详解-----AOP的深刻理解

    标题 "开源框架spring详解-----AOP的深刻理解" 指向的是对Spring框架中核心概念之一的面向切面编程(Aspect Oriented Programming, AOP)的深入探讨。AOP是Spring用来解决横切关注点问题的一种编程模式,它允许...

    AOP练习小例子

    容器,如Spring框架在Java中的应用,或者Unity Container在.NET中的应用,负责管理和组装对象,而动态代理则是AOP的关键技术之一,它可以在运行时创建一个代理类来拦截方法调用,从而插入切面逻辑。 **C#反射**是...

    简易的AOP框架

    在Java中,Spring框架是最著名的AOP实现之一,但这里我们讨论的是一个简易的AOP框架,它可以帮助理解AOP的基本概念和工作原理。 该简易AOP框架包含以下几个关键组件: 1. **配置文件**:这是定义切面(aspect)和...

Global site tag (gtag.js) - Google Analytics