Jbpm,他是jboss下的一个开源项目,是个基于petri net理论为基础的工作流引擎。本文主要通过jbpm源代码分析下jbpm引擎内核工作原理。
Jbpm是基于微内核引擎的基础上扩展开发出来的工作流平台,其运行的核心包是在org.jbpm.graph下,在该包下又分有action、def、exe、log、node几个包,jbpm内核引擎实现逻辑主要存放在def、exe这两个包下,其他的包是基于此内核扩展出来的动作、模型和日志。
下面我们通过一个简单的例子来逐步的分析jbpm是如何工作的。看下面jbpm自带演示的一个hello流程(视乎大家都喜欢从hello实现开始^_^),代码如下:
public void testHelloWorldProcess() {
ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
"<process-definition>" +
" <start-state>" +
" <transition to='s' />" +
" </start-state>" +
" <state name='s'>" +
" <transition to='end' />" +
" </state>" +
" <end-state name='end' />" +
"</process-definition>"
);
ProcessInstance processInstance =new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
assertSame(processDefinition.getStartState(), token.getNode());
token.signal();
assertSame(processDefinition.getNode("s"), token.getNode());
token.signal();
assertSame(processDefinition.getNode("end"), token.getNode());
}
首先,我们定义个流程模板(ProcessDefinition),就是上面代码的ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(….);这段,在括号中是jbpm定义的流程,其中包括三个环节,分别是starts-state、state和end-state。parseXmlString()方法的主要功能是解析这段xml语言返回个流程模板对象(processDefinition)。
接着,通过流程实例类(ProcessInstance)来实例化个流程实例,通过传进来的流程模板对象创建ProcessInstance processInstance =new ProcessInstance(processDefinition)。我们来看看new ProcessInstance(processDefinition)到底做了什么,通过查看ProcessInstance的源代码,可以看到其中主要的一段是
public ProcessInstance( ProcessDefinition processDefinition ) {
//略去其他代码
this.processDefinition = processDefinition; //将流程模板对象付给流程实例
this.rootToken = new Token(this); //创建跟令牌
//略去其他代码
}
我们继续跟进Token这个类
public Token(ProcessInstance processInstance) {
//主要一句如下
this.node = processInstance.getProcessDefinition().getStartState();
}
这样就实现了令牌绑定到开始节点。至此,一个流程实例就创建起来了,并且该流程实例走到了开始节点,即令牌所处的位置。
我们接着往下走token.signal()
public void signal() {
signal(node.getDefaultLeavingTransition(), new ExecutionContext(this));
//这里的getDefaultLeavingTransition()如果有多条路径,则去第一条路径
}
void signal(Transition transition, ExecutionContext executionContext) {
//省略其他代码
node.leave(executionContext, transition);
//省略其他代码
}
这里的node就是刚才令牌所在的开始节点,我们来看看jbpm是如何将令牌从开始节点移到下个节点的。
public void leave(ExecutionContext executionContext, Transition transition) {
Token token = executionContext.getToken();
token.setNode(this);//此时令牌还在开始节点
executionContext.setTransition(transition);
//略去部分代码
executionContext.setTransitionSource(this);
transition.take(executionContext);//实现令牌的转移
}
我们来看看transition.take(..)方法做了什么
public void take(ExecutionContext executionContext) {
//略去部分代码
to.enter(executionContext);//离开开始节点,进入到下个节点
}
大家可能会有点疑问,这个to节点是什么是否初始化的?其实在signal时有句node.getDefaultLeavingTransition(),这句返回Transition对象,该对象就已经初始化了to节点的对象。我们在跟进to.enter(..)
public void enter(ExecutionContext executionContext) {
Token token = executionContext.getToken();
token.setNode(this);//此时令牌就到了名字为“s”的state节点
token.setNodeEnter(new Date());
executionContext.setTransition(null);
executionContext.setTransitionSource(null);
execute(executionContext);
}
在这段代码中的注释这句,真正实现了令牌从开始节点到下个节点了。
至此,jbpm工作流引擎的内部工作原理就介绍完了,其实这就是工作流引擎最核心的部分了,就是如何从一个环节转移到另一个环节。或许你会说“这么简单,我马上就可以写一个”,其实不然,上面我们所用的例子是十分简单的例子,其实在工作流联盟规范中还有其他复杂的节点模型,如split,join,subflow等。不过幸运的是这些复杂的节点模型jbpm都为我们提供了他自己的默认的实现,这些节点模型都在org.jbpm.graph.node包下。jbpm引擎中很好的抽象了节点模型Node类,大部分的复杂节点模型都继承自Node,我们也可以定制自己的节点,只要实现Node类的execute()方法即可方便的实现。其实从上面分析的代码可以看出,Node类主要的逻辑处理是在leave()、enter()和execute()三个方法,大家可以看下ProcessState,join,fork这些节点模型是如何实现的。
以上简单介绍了jbpm引擎内核的工作原理,如有不对的地方还望指正。
posted on 2008-09-16 19:28
囧囧之猪 阅读(4197)
评论(5) 编辑 收藏 所属分类:
workflow