Aspect Oriented Programming(AOP)是近来较为热门的一个话题。AOP,国内 大致译作“面向方面编程”。
“面向方面编程”,这样的名字并不是非常容易理解,且容易产生一些误导。笔者不止 一次听到类似“OOP/OOD11即将落伍,AOP是新一代软件开发方式”这样的发言。显然,
发言者并没有理解AOP的含义。
Aspect,没错,的确是“方面”的意思。不过,华语传统语义中的“方面”,大多数情 况下指的是一件事情的不同维度、或者说不同角度上的特性,比如我们常说:“这件事情要 从几个方面来看待”,往往意思是:需要从不同的角度来看待同一个事物。这里的“方面”, 指的是事务的外在特性在不同观察角度下的体现。
而在AOP中,Aspect的含义,可能更多的理解为“切面”比较合适。所以笔者更倾向 于“面向切面编程”的译法。
另外需要提及的是,AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种 设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,
以获得更加清晰高效的逻辑单元划分。
而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步 骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有 着本质的差异。
上面的陈述可能过于理论化,举个简单的例子,对于“雇员”这样一个业务实体进行封 装,自然是OOP/OOD的任务,我们可以为其建立一个“Employee”类,并将“雇员”相 关的属性和行为封装其中。而用AOP设计思想对“雇员”进行封装将无从谈起。
同样,对于“权限检查”这一动作片断进行划分,则是AOP的目标领域。而通过OOD/OOP 对一个动作进行封装,则有点不伦不类。
换而言之,OOD/OOP面向名词领域,AOP面向动词领域。
AOP和OOD/OOP并不冲突,我们完全可以在一个应用系统中同时应用OOD/OOP和 AOP设计思想,通过OOD/OOP对系统中的业务对象进行建模,同时通过AOP对实体处理 过程中的阶段进行隔离处理。即使不是OOD/OOP,而是在传统的POP(面向过程编程)中,
AOP也能起到同样的作用。
将不同阶段领域加以分隔,这是否就算是AOP呢?
AOP还有另外一个重要特点:源码组成无关性。
11
倘若应用中通过某个具体的业务逻辑类实现了独立的权限检查,而请求调度方法通过预 编码调用这个权限模块实现权限管理。那么这也不算是AOP。对于AOP组件而言,很重要 的一点就是源码组成无关性,所谓源码组成无关性,体现在具体设计中就是AOP组件必须 与应用代码无关,简单来讲,就是应用代码可以脱离AOP组件独立编译。
为了实现源码组成无关性,AOP往往通过预编译方式(如AspectJ)和运行期动态代理 模式(如Spring AOP 和JBoss AOP)实现。
稍后章节中我们会就Spring Framework中的AOP实现机制进行更加深入的探讨。
下面先来看AOP中几个比较重要的概念:
1. 切面(Aspect)
切面,对象操作过程中的截面。这可能是AOP中最关键的一个术语。
我们首先来看一个应用开发中常见的切面:用户权限检查。大概只要是完整的应用,都 少不了用户权限检查这个模块,不同身份的用户可以做什么,不可以做什么,均由这个模块 加以判定。而这个模块调用的位置通常也比较固定:用户发起请求之后,执行业务逻辑之前。
针对权限检查这一模块进行分离,我们就得到了一个切面:
切面意义何在?
首先根据上例,假设我们实现了一个通用的权限检查模块,那么就可以在这层切面上进 行统一的集中式权限管理。而业务逻辑组件则无需关心权限方面的问题。也就是说,通过切 面,我们可以将系统中各个不同层次上的问题隔离开来,实现统一集约式处理。各切面只需 集中于自己领域内的逻辑实现。
这一方面使得开发逻辑更加清晰,专业化分工更加易于进行;另一方面,由于切面的隔 离,降低了耦合性,我们就可以在不同的应用中将各个切面组合使用,从而使得代码可重用 性大大增强。
2. 连接点(JoinPoint)
程序运行过程中的某个阶段点。如某个方法调用,或者某个异常被抛出。
3. 处理逻辑(Advice)
在某个连接点所采用的处理逻辑
(这里的Advice,国内不少文案中翻译为“通知”,估计是源于金山词霸,与实际含义不符,因而这 里采用意译)
处理逻辑的调用模式通常有三种:
i. Around
在连接点前后插入预处理过程和后处理过程。
ii. Before
仅在连接点之前插入预处理过程。
iii. Throw
在连接点抛出异常时进行异常处理。
4. 切点(PointCut)
一系列连接点的集合,它指明处理方式(Advice)将在何时被触发。
上述几个概念我们将在稍后的“AOP应用”一节中结合实际使用进行具体探讨。