1、单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,*,面向方面的程序设计,兼谈计算科学的创新,哈尔滨工程大学 计算机学院,刘大昕,Email,:,ldx12399,sina,.com,1,面向方面的程序设计,Aspect oriented programming(AOP),2,Xerox(,施乐,),公司,PARC,研究中心在,1997,年的欧洲面向对象编程大会(,ECOOP97,),上首次提出,Aspect-oriented programming(,AOP,),。,自,2002,年起,每年分别在欧洲和美国轮流召开专门的面向方面软件开发(,AOSD
2、国际会议。与会者包括美国、加拿大、荷兰、英国、法国、丹麦、日本、以色列等。我国一些学校也对,AOP,给以关注并开展了一些研究工作。,从,AOP,概念提出经过了近十年的时间,这种技术现在已经开始被工业界采用。,3,AOP,产生的背景,计算机软件设计的一个重要原则,就是要清晰,分离各种关注点,(,separation of concerns,),,然后分而治之,各个击破,最后形成统一的解决方案。,业务逻辑,存储,日志,安全,需求,关注点,标识,4,关注点:是指一个特定的目标、概念或者兴趣域。,从技术的角度,软件系统分别包括,核心级和系统级,的关注点。,核心级关注点是系统要完成的,业务功能,;
3、系统级关注点是完成核心级关注点所必须的,配套设施,,这些配套设施通常被认为是整个系统的系统特性,或者是业务功能的功能约束。,例如:信用卡处理系统,核心关注点是,处理付款,;,系统级关注点包括,日志、事务、认证、安全和性能,等等。,5,软件系统中,某个行为,例如操作日志的记录,存在于软件的各个部分中,这个行为可以看作是横向存在于软件之中,他所关注的是软件的各个部分的一些共有的行为。,在很多情况下,这种行为不属于业务逻辑的一部分。这种操作并不是业务逻辑调用的必须部分,但是,我们却往往不得在代码中显式进行调用,并承担由此带来的后果。,6,在目前的技术框架下,通常,系统级关注点在,逻辑上,相互之间,
4、彼此正交(相互独立),,同时在,实现上,趋向于,和若干核心模块交织,。,例如:信用卡管理系统的每个核心业务关注点都和安全、日志等系统关注点相联系。,7,核心级关注点,(业务)多数情况下可以被很好地分解,并,通过编程语言模块化实现(子模块或软构件),。,系统级关注点,(横向关注点),使用当前的程序设计方法导致,在许多构件中要重复包含(扩散)这些代码,。,8,横切示例,(,crosscutting),Authentication,权限,Caching,缓存,Context passing,内容传递,Error handling,错误处理,Lazy loading 懒,加载,Debugging,调试
5、Logging,、,tracing,、,profiling and monitoring,日志、跟踪、优化、校准,Performance optimization,性能优化,Persistence,持久,化,Resource pooling,资源,池,Synchronization,同步,Transactions,事务,9,现有软件技术的不足,目前的实现技术只提供了,一维方法学实现系统的关注点,,该单一维度一般是核心需求和关注点的模块化实现,,其他类型的需求也被迫和该主导维度一致。,安全,事务,业务,业务主导维,问题空间是,n,维的,而解空间是一维的。这种失配必然导致需求和实现之间的失配。,
6、10,源程序就会变成一些为不同关注目的而编制的,指令的缠结混乱物。,缠结现象,是现有软件系统中许多不必要的,复杂性的核心,。,它增加了功能构件之间的依赖性,,分散了构件原来假定要做的事情,,提供了许多程序设计出错的机会,,使得一些功能构件难以复用,,源代码难以开发、理解和发展。,11,某一应用的领域专家,不太可能对分布、认证、访问控制、同步、加密、冗余等问题的复杂实现机制很熟悉,所以就不能保证他们在程序中进行正确的调用。,开发人员很难正确预见到未来对程序的新需求,。,12,方面(,Aspect,),设计上讲,是横切系统的一些软件系统级关注点。,实现上讲,它支持将横切系统的关注点封装在单独的模块
7、单位中,它是,AOP,将横切关注点局部化和模块化的实现机制。,常见的“,方面,”:,异常和出错处理,同步和并发控制,内存访问模式,日志、安全,事务、性能,13,AOP,核心内容就是所谓的,“,横切关注点,”,,即,“,方面,”,,,Aspect,是,AOP,提供的一种程序设计单元。,而在,OOP,中,这些一般关注点的实现单元叫作类,AOP,的目标,是要将这些横切关注点与业务逻辑代码相分离,从而得到更好的软件结构、性能以及稳定性等方面的好处。,AOP,被认为是后面向对象时代的一种新的重要的程序设计技术。,14,AOP,的基本思想,通过分别描述系统的不同关注点及其关系,以一种松耦合的方式实现单个关
8、注点,然后依靠,AOP,环境的支撑机制,将这些关注点组织或编排成最终的可运行程序。,普通关注点可以使用传统的结构化方法和面向对象方法体统的机制。,系统关注点使用,Aspect,机制。,15,AOP,程序设计的一般步骤,一、,对需求规约进行,Aspect,分解。,确定哪些功能是组件必须实现的,即提取出,核心关注点。,哪些功能可以以,aspect,的形式动态加入到系统组件中去,即提取出系统级的,横切关注点,。,16,AOP,程序设计的一般步骤,二、,对标识出的,Aspect,分别通过程序机制实现。,构造系统的组件。,利用,组件语言,实现系统的组件。对于,OOP,语言,这些组件可以是类;对于过程化程
9、序设计语言,这些组件可以是各种函数和,API,。,构造系统的,aspect,。,利用一种或多种,aspect,语言,实现,aspect,。,aspect,语言必须提供声明,aspect,的机制。,aspect,如何声明,连接点如何定义,aspect,代码如何定义,aspect,的参数化程度等,17,三、,用,aspect,编织器将所有的单元编排重组在一起,形成最终的可运行系统。,为组件语言和,aspect,语言构造相应的语法树;依据,aspect,中的连接点定义对语法树进行联结;在连接的语法树上生成中间文件或目标代码。,aspect,语言必须提供将,aspect,代码和基础代码组合编排(,we
10、aving,),在一起的机制。,定义编排语言和规则。,解决,aspect,之间潜在的冲突。,为组装和执行建立外部约束。,aspect,语言必须提供生成可运行系统的实现机制。,系统的组合是在编译时静态组装还是运行时动态进行。,对程序单元分别进行编译的模块化编译机制。,对组装结果的验证机制等。,18,AOP,的本质,将横切关注点(如日志、权限验证、并发控制等非功能需求,),单独用,aspect,实现,而业务功能用现有的软件技术实现。由,AOP,机制提供将这些分离的关注点编织为一个可执行程序。,提高代码的可理解性、可维护性、可复用性等。,横切关注点,19,AOP,系统的软件开发过程,业务逻辑,存储,
11、日志,安全,需求,关注点,标识,编织器,Aspect,分解,Aspect,重组,20,AOP,与,OOP,比较,OOP,是,AOP,的技术基础,,AOP,是对,OOP,的继承和发展。,可扩展性:,指软件系统在需求更改时程序的易更改能力。,OOP,主要通过提供继承和重载机制来提高软件的可扩展性。,AOP,通过扩展,Aspect,或增加,Aspect,,,系统相关的各个部分都随之产生变化。,21,可重用性:,指某个应用系统中的元素被应用到其他应用系统的能力。,OOP,以类机制作为一种抽象的数据类型,提供了比过程化更好的重用性。,OOP,的重用性对非特定于系统的功能模块有很好的支持,如堆栈的操作和窗
12、口机制的实现。,对于不能封装成类的元素,如异常处理等,很难实现重用。,AOP,使不能封装成类的元素的重用成为可能。,22,易理解性和易维护性,代码缠结问题的存在,使,OOP,技术在易理解性和易维护性方面都难有很大的提高。,统计发现:“如果一个他人写的程序有,37,处需要改动,对于一个最优秀的软件开发人员,也大概只能找到,35,个”。,对于,AOP,,,对一个,Aspect,修改可以通过联结器影响到系统相关的各个部分,从而大大提高系统的易维护性。,23,AOP,特性,Aspect,的实现和传统开发方法中,模块的实现不同,。,Aspect,的开发彼此独立,是一种松耦合关系。,主代码的开发者甚至可能
13、没有意识到,aspect,的存在。只是在最后系统组装时,才将各,aspect,代码和主代码编排融合在一起。,主代码和,Aspect,之间采用,“,隐式调用,”,。,某一应用的领域专家,不太可能对分布、认证、访问控制、同步、加密、冗余等问题的复杂实现机制很熟悉,所以就不能保证他们在程序中进行正确的调用。,开发人员很难正确预见到未来对程序的新需求。,24,AspectJ,AspectJ,是,Xerox PARC,开发的基于,Java,语言的,AOP,扩展,它既是一种规约语言,也是一种,AOP,的实现语言。,AspectJ,是一种支持“面向,Aspect”,概念的语言。,25,AspectJ,Asp
14、ectJ,提供了支持“面向,Aspect”,概念的如下语言结构及定义:,Joinpoints,:,预定义好的程序的特定执行点。,例如:,方法的调用和执行,对属性的读写访问,异常处理,对象和类的初始化执行,构造器的调用和执行,26,Pointcuts,:,用来指明所需连接点的语言元素,。,可能包括一系列的连接点,,,同时它还可以为在连接点上执行的通知提供上下文,。,例如:,pointcut callSetter,();call(public void,HelloWorld,.set*(.),。,其中:,pointcut,说明声明的是一个切入点,命名,callSetter,,,后面的空括号表示该切
15、入点不需要上下文信息。,Call,表示该切入点捕获的是对指定方法的调用,指定的方法是在类,HelloWorld,中声明的共有的、返回值为空、以,set,开头、拥有任意参数的方法。,27,Advices,:,要在,Pointcuts,执行的,Aspect,的代码。,AspectJ,提供了,3,种把通知关联到连接点的方式:,after,、,before,、,around,。,after,和,before,分别表示通知在连接点的前面或者后面运行,,around,则表示通知在连接点的外面运行,并可以决定是否运行此连接点。,例如:,在银行信息系统中,实现帐户存取模块、权限验证模块和日志记录模块。帐户存取
16、模块可用,OOP,技术来实现,其他的模块可采用,AOP,技术。,在,around,通知中验证权限,只有验证通过才运行该连接点,在,before,和,after,通知中就输出日志记录。,Aspect,:,上述三者的结合。以类似于类的概念,将,Pointcut,和,Advice,组合在一起,形成一个程序单元。,28,AspectJ,为程序员提供了编译、调试等工具。,Aspect,编排器,将不同,aspect,组装到一起。,Aspect,调试器,独立的,Aspect,浏览器,和一些流行的,IDE,环境(,Forte,、,Jbuilder,、,Emacs,),的集成。,AspectJ,可以引入新的数据
17、成员和新的方法。,29,应用示例,1:,一个简单的使用面向对象方法设计的,图元编辑器,的示例。,在该图元编辑器中,抽象图元类,FigureElement,有两个图元子类,Point,和,Line,,,分别对点和线进行管理。这两个类体现了良好的模块性,类中源代码都紧密相关,内聚度很高,并且每个类的接口都很清晰,。,显示更新的需求:无论图元何时移动、移动到哪里,都要通知屏幕管理器(,Display,),其位置发生了改变。,30,采用面向对象的设计方法,典型的做法是在每个移动图元的操作代码中,都插入一段通知,Display,其位置发生了改变的代码(调用,Display.update(),方法),如图
18、所示。,Class Line,private Point _p1,_p2;,Point getP1()return _p1;,Point getP2()return _p2;,void setP1(Point p1),this._p1=p1;,Display.update();,void setP2(Point p2),this._p2=p2;,Display.update();,Class Point,private,int,_x1,_x2;,int,getX,()return _x1;,int,getY,()return _x2;,void,setX,(,int,x1),this._x1=
19、x1;,Display.update();,void,setY,(,int,x2),this._x2=x2;,Display.update();,31,Aspect,DisplayUpdating,Pointcut,move():,call(void Line.setP1(Point)|,call(void Line.setP2(Point)|,call(void Point.,setX,(,int,)|,call(void Point.,setY,(,int,);,after()returning:move(),Display.update();,Class Line private Poi
20、nt _p1,_p2;Point getP1()return _p1;Point getP2()return _p2;void setP1(Point p1)this._p1=p1;void setP2(Point p2)this._p2=p2;,Class Point private,int,_x1,_x2;,int,getX,()return _x1;,int,getY,()return _x2;void,setX,(,int,x1)this._x1=x1;void,setY,(,int,x2)this._x2=x2;,32,假设我们想用,aspect,做以下的事情:,在任何对象调用,Te
21、stClass,.,sayHello,(),方法的前后打印一条消息。,测试,TestClass,.,sayAnyThing,(),方法的参数至少有三个字符。,public class,TestClass,public void,sayHello,(),System.out.,println,(“Hello,,,AOP”);,public void,SayAnyThing,(String s),system.out.,println,(s);,),public static void main(String,args,),TestClass,t=,newTestClass,(),;,t.,say
22、Hello,();,t.,sayAnyThing,(“ok”);,应用,2,33,public aspect,MyAspect,public,pointcut sayMethodCall,(),:,call(public void,TestClass,.say*(),;,pub1ic,pointcut,sayMethodCal1Arg(String,str,),:,call(public void,TestClass,.,sayAnyThing,(string)&,args,(,str,),;,before(),:,sayMethodCal1(),System.out.print1n(“,nT
23、estClass,.”+,thisJoinPointStaticPart,.,getSignature,().,getName,()+”start”),;,after(),:,sayMethodCal1(),System.out.print1n(“,nTestClass,.”+,thisJoinPointStaticPart,.,getSignature,().,getName,()+”end”),;,before(String,str,),:,sayMethodCallArg,(,str,),if(,str,.1ength(),3),System.out.,println,(“Error,:
24、I,cant say words less than 3 characters,”,),;,return,;,34,应用示例,3,:例外处理,以数据库查询为例,分别用,OOP,的,Java,语言,和,AOP,的,AspectJ,语言加以 实现。,public class,DBQuery,public,ResultSet,executeQuery,(String,sql,),try,/,数据库连接操作,/,数据库查询操作,catch(java.lang.,ClassNotFoundException,e),/,对,ClassNotFound,例外进行处理,catch(,SQLException
25、e),/,对,SQL,例外进行处理,catch(Exception e),/,对其他例外进行处理,35,分析以上代码,主要存在以下几点不足:,要求编程人员掌握大量的例外类库和复杂的语法结构,实际应用中容易出错;,对例外的处理并不是,DBQuery,类的核心功能,但编程人员要花费大量精力在例外的处理上,而忽略了问题本身;,当,DBQuery,所在类包中定义了多个类或,DBQuery,中定义了多个方法时,(,如数据库记录的添加、更新、删除等操作),就要重复定义多个相同的例外处理;,大量的例外处理代码可能引起更多的不必要错误,给程序调试和维护带来了困难;,基于以上几点,可认为它是有安全隐患和不健壮
26、的程序。,36,基于,AOP,安全编程的思想,在,DBQuery,类中保留单纯的数据库连接和查询代码,而将其中实现例外处理的代码抽取出来,组织成单独模块。,37,aspect,ExHandle,declare soft:Exception:within(,DBQuery,),;,pointcut,Callmethod,(,DBQuery,query):this(query)&call(*,DBQuery,.*(.),;,after,(,DBQuery,query)throwing(,java.lang.,ClassNotFoundException,e,):,Callmethod,(query
27、),/,对,ClassNotFound,例外进行处理,after,(,DBQuery,query)throwing(,SQLException,e,):,Callmethod,(query),/,对,SQL,例外进行处理,after,(,DBQuery,query)throwing(,Exception e,):,Callmethod,(query),/,对其它,例外进行处理,38,以下几方面为突出的安全优点:,程序开发人员可专注于数据库连接和查询操作本身,而无须同时考虑对例外的处理;,安全代码被独立到单独的,aspect,中,使程序更易理解,且当安全策略需要修改时,只需变动,ExHandle
28、代码,而无需改动,DBQuery,类;,当添加新的类或,DBQuery,类中添加新的方法时,编程人员不必考虑新的错误处理策略,甚至不必去了解这些策略,,ExHandle,代码将自动应用于它们。,39,应用,4,:一个异常处理的实例,下面的代码是一个简单的方面的例子,它打印所有的没有被包中定义的任何方法处理的异常。我们能在测试时使用这个代码,看是否有没预料到的错误,由此指出包中的一个漏洞。,public aspect,ExceptionPrinter,pointcut allMethods,(),:,executions(*(,),;,static after()throwing(Except
29、ion e),:,allMethods,(),System.out.,println,(“Uncaught exception,:”,+e),;,40,应用,5,:,AOP,技术在并发访问控制中的应用,当多个线程要访问同一个变量或对象时,为了保证数据的一致性,要实施一些并发访问控制策略。,通常的做法是采用加锁和解锁的方法。即多个访问类同时访问一个共享数据对象时,每个访问类在访问这个数据对象时,将数据对象上锁,访问完成后,再解锁,供其他并发线程访问。,worker,Another,worker,数据对象,上锁,解锁,上锁,解锁,41,public aspect Lock,ReentrantWri
30、terPreferenceReadWriteLock rwl,=new,ReentrantWriterPreferenceReadWriteLock,();,public,pointcut writeOperations,():,execution(public,boolean,Worker.,createData,()|execution(public,boolean,Worker.,updateData,()|execution(public,boolean,AnotherWorker,.,updateData,();,before():,writeOperations,(),rwl,.,
31、writeLock,().acquire();/,在写操作之前上锁,after():,writeOperations,(),rwl,.,writeLock,().release();/,在写操作之后解锁,42,AOP,研究内容,Early aspects:aspect-oriented requirements engineering and architecture design.,Aspect-oriented modeling and design,Design patterns for aspect-oriented systems,43,Aspect-oriented program
32、ming languages,platforms and frameworks,Type systems for aspects,Composition models and operators for aspects,Optimization and performance improvement of aspect-oriented composition,44,Application of AOSD in specific areas such as embedded systems,banking systems,ambient computing,etc.,Aspects in fe
33、ature-oriented approaches and product lines.,Aspects in reengineering,45,小结,AOP,起源于程序设计中“横切”引发的“代码散布”和“代码交织”问题。在目前的程序设计技术下,程序中的横切无法避免,其实现代码相互纠缠在一起,是软件复杂度的来源之一。,AOP,就是要能分离出那些隐含的、相互交织纠缠的系统关注点,并使之明确。使用,AOP,为程序员提供的新的模块化武器,横切的代码就可以局部化,程序的结构很明白,代码也常常很简短。,46,面向,方面,不仅,在增加分割系统特性上的价值,对基本系统的安全性、日志、持久性、调试、跟踪、分布
34、式、执行监控等。,方面的,另一个,重要的目的是,提供了一个,把用例与方面连接起来,的新范型,。,(,在现存的构件模块性的顶端增加用例模块,),47,子用例,异常用例,异常用例,异常用例,基本用例,面向方面技术也使,UML,中用例模块化,48,子用例,异常用例,异常用例,异常用例,基本用例,编织器,49,可以肯定的是:,AOP,不会是处理关注点分离问题的最后解决方案。,如果,AOP,对系统关注点的分离粒度太细,则会适得其反,导致模块间关系更加复杂,反而使复杂度增加。因此,应用,AOP,时仍然要遵从良好的设计原则,只分离需要分离的关注点。,50,AOP,的概念也就是面向方面的软件开发(,AOSD,
35、将会使我们可以完美的继承已经存在的软件,在,系统的整个生命周期中,可以不断的进行开发迭,代和不断的发布更新版本。,我们今天叫做面向方面的技术将把软件生命周,期成本降低至少,20,。,51,它与“子程序”概念十分相像,但是,不是所有的关注点都能很利索地通过子程序实现。,子程序调用的程序员必须对调用的子程序有足够的了解。,一段程序必须知道要显式地调用另一段子程序,并且知道怎样去调用,这极大限制了程序员并行独立解决子问题的能力。,52,这不是一种横空出世的新思想,它依赖于十年前就已经众所周知的补丁技术(补丁技术已成为专利技术!)。然而什么是新的呢,?,就是实现了,“,正确地打补丁,”,,把补丁技术系统化、抽象化和形式化,这正是理解复杂系统的最自然方式。,53,反向思维,保持原衣服不动,把在何处打补丁的信息写在补丁上。,大部分创新的基本思想都来自日常生活,而且原理简单,打补丁反向打补丁,系统化、抽象化、形式化,实现两次创新!,54,希望寄托在年轻人身上!,55,谢 谢,再 见,56,






