AOP是一个概念,它自身没有设定具体的语言实现,但这实际上提供了非常广阔的发展空间。面向过程的时代已经离我们而去,面向对象才是现在软件世界的潮流。而面向方面编程为我们带来了新的想法、新的思想。下面我们就AOP进行了解。
在讲解AOP的概念之前,我们要先了解一下为什么我们要区分J2EE应用系统和J2EE容器?要知道,J2EE应用系统只能在J2EE容器中使用,那为什么还要区分这两者呢?实际上J2EE容器分离了一般应用系统的一些通用功能:安全机制、对象池等等。对于每个应用系统来说这些机制几乎都需要,所以可以从应用系统中提取出来,弄成了一个通用的框架平台。
但是这些功能机制的开发具有一定的难度,而且运行的稳定性和快速性都很重要,必须经过长时间的调试和运行经验积累而成。所以出现了专门的J2EE容器服务器产品:Tomcat JBoss、WebLogic等。
分散关注
从J2EE系统划分为J2EE容器和J2EE应用系统,我们可以从中看到一种分散关注的思路。将系统通用的需求功能从不相关类中提取出来。同时能够使得很多类共享一个行为,一旦行为发生变化,只要修改这个行为就可以直接修改很多的类
AOP概念
AOP是Aspect Oriented Programming的缩写,意思是面向方面编程。可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP是OOP的延续也可以说AOP是GoF设计模式的延续,设计模式追求的是调用者和被调用者之间的解耦,也可以说AOP是这种目标的实现。注意:AOP不是一种技术,实际上是编程思想。凡是符合AOP思想的技术,都可以看成是AOP的实现。
联结点(JointPoint) :一个联结程序执行过程中的一个特定点。典型的联结点有:调用一个方法;方法执行这个过程本身;类初始化;对象初始化等。联结点是 AOP 的核心概念之一,它用来定义在程序的哪里通过 AOP 加入新的逻辑。
切入点(Pointcut) :一个切入点是用来定义某一个通知该何时执行的一组联结点。通过定义切入点,我们可以精确地控制程序中什么组件接到什么通知。上面我们提到,一个典型的联结点是方法调用,而一个典型的切入点就是对某一个类的所在方法调用的集合。通常我们会通过组建复杂的切入点来控制通知什么时候被执行。
通知(Advice) :在某一个特定的联结点处运行的代码称为“通知”。通知有很多种,比如
在联结点之前执行的前置通知(before advice)和在联结点之后执行的后置通知(after advice) 。
方面(Aspect) :通知和切入点的组合叫做方面,所以,方面定义了一段程序中应该包括的逻辑,以及何时应该执行该逻辑。
织入(Weaving) :织入是将方面真正加入程序代码的过程。对于静态 AOP 方案而言,织入是在编译时完成的,通常是在编译过程中增加一个步骤。类似的,动态 AOP 方案则是在程序运行是动态织入的。
目标(Target) :如果一个对象的执行过程受到某一个 AOP 的修改,那么它就叫一个目标对象。目标对象通常也称为被通知对象。
引入(Introduction) : 通过引入,可以在一个对象中加入新的方法或属性,以改变它的结构,这样即使该对象的类没有实现某一个接口,也可以修改它,使之成为该接口的一个实现。
例子:在一个应用系统中,有一个共享的数据必须被并发同时访问。当我们将这个数据封装在数据对象中(Data Class)后,会将有多个访问类会专门用于在同一时间访问这同一个数据对象。而这时候我们就要引入锁lock的概念用于完成上述并发访问统一资源的功能。在引入Lock的概念之后,某一时刻有一个类访问这个数据对象的时候,这个数据对象必须上锁,在用完之后解锁,再让其他的类访问。
这个应用的“锁”,有以下的特点:
“锁”行为其实是可以和具体访问类的主要功能独立区分开来的。
“锁”功能主要是访问数据对象,并不是具体访问类的主要功能。
“锁”功能其实是这个系统的一个纵向切面并且涉及许多的类以及类的方法。
#p#分页标题#e#
因此在一个新的程序结构中我们应该关注的是纵向切面,比如这一应用的“锁”功能,在这个应用中“锁”方面应该有以下的职责:提供一些像对被访问对象实现加锁或解锁的功能。用于保证所有修改数据对象的操作之前能够用Lock()加锁,并在使用之后解锁(unlock())。
在传统的编程习惯中,我们会创建一个抽象类并让所有的访问类继承这个抽象父类。
但是引入Lock的概念有几个的缺点:
在java中,只提供了单继承,所以当访问类继承这个父类之后,就不能方便的继承其它的父类。
AccessDataObject()方法需要有“锁”状态之类的代码。
重用打折扣,具体访问量也只能被重用在相关有“锁”的地方,因为具体访问类中也含有包含“锁”状态之类的代码。
AOP/OOP区分
虽然两者字面上非常相似,但是确实截然不同领域的两种设计思想。OOP是面向对象编程,而AOP是面向方向编程。简单来说,OOP面向名词领域,AOP面向动词领域。
AOP真的有必要吗?
对于上述的例子来说,不使用AOP也可以得到解决,在JBoss中也提供了上述的应用功能。
但是因为使用了AOP结构,现在JBoss 4.0的源码会比JBoss 3.X容易理解,对于一个大型并且复杂的系统来说是非常重要的。而且使用AOP可以让我们从一个更高的抽象概念来理解软件系统。
AOP的应用范围
目前的JBoss 4.0正是由AOP框架进行开发,所以我们可以看出AOP非常适合J2EE容器的开发。
它的具体功能如下:
Authentication 权限
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 懒加载
Debugging 调试
logging, tracing, profiling and monitoring 记录跟踪 优化 校准
Performance optimization 性能优化
Persistence 持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务
AOP的具体实现
AOP并没有设定具体的语言用于实现,因为AOP是一个概念,它能克服那些只有单继承语言的缺点,就AOP目前来说,具体实现的有以下这些项目:
动态AOP:使用JDk的动态代理API或字节码Bytecode处理技术。
AspectJ:创建于Xerox PARC。有近十年历史,但是使用过于复杂,并且破坏封装,需要专门的java编译器。
基于动态代理API的项目有:JBoss 4.0、nanning、JdonFramework。
基于字节码的:aspectwerkz、spring
spring AOP使用纯java实现,不需要专门的编译过程。Spring AOP不需要控制类装载器层次,因此它适用于J2EE web容器或应用服务器。
面向方面编程是一个新的模式,就对于软件系统来说,或许它的影响力会如同面向对象一般巨大。它们两者间有着良好的互补关系。有了AOP我们可以定义交叉的关系并将这些关系应用于跨模块的、彼此不同的对象模型。