Posted on 2006-10-22 18:44
canonical 阅读(1253)
评论(0) 编辑 收藏 所属分类:
设计理论
IoC(Inversion of Control)是一个很宽泛的概念,对于我们常说的IoC容器(如spring)所做的工作,一个更加准确一些的说法是依赖注入(Dependency Injection), 即容器将一个对象所依赖的其他对象push到该对象中,而不是该对象从外界环境pull相关的依赖对象. 不过, 细究起来这种依赖注入仍然只是DI的一种特殊形式, 可以将它称之为data dependency injection, 因为IoC容器所许诺的是: "啊哈, 当我们需要对象A的时候,它就在这儿". 虽然IoC容器管理的不仅仅是数据,而是具有行为的对象,但是如果要让这些行为具体发生, 我们仍然需要额外的调用步骤.
对于一个自动触发behaviour的系统, 我们一般将之称之为引擎(Engine). 例如工作流引擎在处理完本步骤的业务逻辑之后会自动触发流程流转操作. 一个引擎对于我们的承诺是: "当我们需要某个behaviour的时候, OK, 它会在适当的时候发生的". 对于一个软件开发框架或者更宏大的软件开发平台而言, 如果我们以业务逻辑为主体来审视整个程序运行过程, 则它们的核心价值也在于在适当的时候将适当的操作Inject到业务逻辑中. 对于目前所谓的软件开发平台而言, 除了工作流的内容之外, 一个主要部分就是CRUD(Create/Read/Update/Delete) Ready. 一个开发平台的优劣往往直接体现在它在多大程度上能够将CRUD操作剥离出主体程序逻辑, 这不仅仅涉及到数据库存取操作, 同时还包含界面交互, 数据逻辑关联等.
除了引擎,框架,平台等应用层面的实现之外, AOP(Aspect Oriented Programming)在语言层面为behaviour注入也提供了一种特定的实施手段. 在AOP的概念中, 往往作为切点的函数被认为是基础的部分, 而interceptor是在基础蓝图上的一种扩展. 这也体现在基础函数定义了当时执行环境中可以访问的状态变量(参数/属性),而interceptor则依附于pointcut处所能得到的状态变量, 它本身一般并不维护独立的状态变量(不产生也不消灭状态变量). 从数学上看, base function和interceptor之间构成一种对偶(dual)关系, 当我们的关注重点转移到interceptor上来之后, 它本身也应该具有完整的业务语义, 这需要对AOP的执行过程做小小的偏置处理.
在witrix平台的BizFlow设计中,BizFlow是通过类似AOP的方法作为CRUD操作的Filter实现的, 但是从bizflow本身的配置文件来看,它可以构成一个完整的业务描述, 而CRUD成为某种自动注入的behaviour.例如对于新增操作, BizFlow中的配置可以如下
<action id="Add-default">
</action>
虽然没有写任何代码, 新增操作(包括从request中读取操作并做有效性校验等操作)是自动进行的. 我们也可以在新增前和新增后分别执行一些操作
<action id="Add-default">
<source>
some operation before add
<biz:Proceed/>
some operation after add
</source>
</action>
与AOP中的常见做法不同, 这里并没有明确定义新增前和新增后这样的切点, 而只是定义了Add-default这样一个action. 在BizAction的source段可以执行任何tpl代码, 而tpl代码的执行上下文可以看作一个Map, tpl代码执行过程中可以获取变量, 也可以设置任意变量, 因而bizFlow拥有对于状态空间的完全的控制权.