Posted on 2006-11-19 19:59
canonical 阅读(2728)
评论(6) 编辑 收藏 所属分类:
设计理论
随着IoC(Inversion of Control)容器的流行,AOP(Apsect Oriented Programming)似乎逐渐成为了主流技术的一部分,但是除了Transaction, Lazy Load, Cache, Log等少量样板应用之外,AOP的技术价值究竟何在? 它能否在广泛的领域发挥作用? 为什么考虑到传统领域之外的应用时,我们的想象力是如此的贫乏?回答这些问题需要对AOP的技术实质作详细的审视.
传统上, 程序的结构是静态的. 定义了一个类, 它的成员变量和成员函数就是确定的了,定义了一个函数, 它的具体实现也是确定的. 传统程序设计主要定义了一些固化的规则来规范这些确定性组分的组合关系,如类继承体系所表达的推理关系. 而AOP是一种动态代码织入技术, 抽象的说, 一维拓扑的基本元素是线段与边, 而AOP通过mixin, interceptor等机制可以自由的实现这些元素之间的自由组合而不拘泥于预制的规则. AOP就像是一把锋利的砍刀, 我们用它从最终所期望的程序结构中随意的砍下一部分来, 起个名字,就叫Aspect吧. 实际上AOP技术本身并没有限定程序中哪些部分可以作为Aspect, 这种技术本身并不保证你可以抽象得出真正有价值的Aspect, 它只是一种纯粹的程序结构操纵技术而已.
AOP技术有两个主要组成部分: 定位技术和定位后的组装技术. 定位技术是AOP所宣称的无侵入性的关键所在. 如果我们使用interface等机制来实现功能,则要在程序各处写下调用语句:
interfaceA.methodA();
...
interfaceA.methodB();
这可以看作是一种占位技术. 定位技术则一般不需要预先在程序中写下什么调用语句, 根据外部的某些定位规则,我们可以在基础的程序结构中搜索到适当的位置. 在理论上说,这种定位方式非常灵活, 即可以是非常精准的定位到某个点,也可以是非常宽泛的定位到一组切入点. 但是, 这里的一个隐含假设是程序基础结构本身已经具备了良好的,具有某种均一性的坐标系, 只有这样我们才能够拥有定位所需的基本信息. 想象一下,如果整个程序只有一个函数, 所有功能的实现通过传入不同的参数值来实现, 则这样的程序结构中是没有什么可定位性而言的. 早期AOP定位所能够依赖的坐标只有类,方法名称, 方法参数类型等, 而这些信息本身又具有自己的业务含义,随着业务的发展,它们本身的名称也可能需要不断的变化,这直接造成AOP所依赖的坐标系的不稳定性.今天还有效的位置描述, 明天也许就突然包括了某些不应该包含进来的程序位置或者排除了某些应在其中的位置. 在JDK5.0中补充的annotation机制为程序补充了新的坐标维度, 基于它无疑可以建立更加灵活而且专用的坐标系统, 它对于AOP的价值必然会逐渐被发掘出来. 在javascript这样的动态语言中,虽然它们内置的动态性直接支持程序结构的动态组装, 但是在定位支持方面却要比java这样的语言弱上很多, 在其上建立AOP应用未见得比java更具优势. 从另外一个角度上说, 定位方式也并不总比占位方式优越. 我们需要牢牢记住"一次描述"的优势在于可以"多次应用". 有的时候我们用很多唇舌去描述一个物品看起来像什么什么样, 有多么大, 多么重, 还不如直接拿给人看, 说:嘿, 就是这个(this).同样在程序中, 占位方式可能更加直接简单,甚至因为代码明确写在那里,概念也更加明确,更加完整. 此外, 在一些特定的程序结构中, 需要定位的位置大大减少, 我们也不需要复杂的定位机制. 例如在witrix的jsplet框架中, 因为它特殊的规范一致性造成程序的处理点只有一个, 应用AOP是一个非常直接的过程.
AOP的第二个组成部分是组装技术. 程序结构的组装在java中早已不是什么技术难点, 很多人干起这活来都是轻车熟路. 但是组装不仅仅意味着程序结构的融合, 它同时意味着程序运行时状态空间的融合. 在AOP的基础模型中, 在切入点可以得到的变量有this指针,调用函数对象和传入参数列表, 但是AOP本身并没有进一步规范化这些变量的具体形式, 因此在一般情况下, 这些变量对于interceptor来说是只读的, interceptor之间也无法通过这些变量交换信息并协同运行. 这实际上意味着在切点处inteceptor的状态空间是极端受限的. 而当一个切面横跨很多切点的时候, 在interceptor中一般只能对切点处状态空间的共性部分进行操作, 这进一步限制了interceptor的能力.实际上目前AOP的主要应用都是无状态的,或者是基于全局状态空间的(例如transaction interceptor只访问线程上下文), 这反映出对于AOP的primitive方式的应用的一种局限性. 在witrix平台的BizFlow设计中,通过对状态空间明确建模, 实现了基于AOP概念的一种新的应用方式.
AOP需要对程序坐标空间和状态空间的良好规划, 才能保证无缝的织入, 保证信息交互通道的通畅.应用AOP所指的不仅仅是配置使用现有的AOP实现, 基于这种程序结构操控技术我们所需要做的抽象工作还很多.