??xml version="1.0" encoding="utf-8" standalone="yes"?>
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());
}
首先Q我们定义个程模板QProcessDefinitionQ,是上面代码的ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(….);q段Q在括号中是jbpm定义的流E,其中包括三个环节Q分别是starts-state、state和end-state。parseXmlStringQ)Ҏ的主要功能是解析q段xml语言q回个流E模板对象(processDefinitionQ?br />
接着Q通过程实例c(ProcessInstanceQ来实例化个程实例Q通过传进来的程模板对象创徏ProcessInstance processInstance =new ProcessInstance(processDefinition)。我们来看看new ProcessInstance(processDefinition)到底做了什么,通过查看ProcessInstance的源代码Q可以看到其中主要的一D|
public ProcessInstance( ProcessDefinition processDefinition ) {
//略去其他代码
this.processDefinition = processDefinition; //流E模板对象付l流E实?br />
this.rootToken = new Token(this); //创徏跟o?br />
//略去其他代码
}
我们l箋跟进Tokenq个c?br />
public Token(ProcessInstance processInstance) {
//主要一句如?br />
this.node = processInstance.getProcessDefinition().getStartState();
}
q样实C令牌l定到开始节炏V至此,一个流E实例就创徏h了,q且该流E实例走C开始节点,即o牌所处的位置?br />
我们接着往下走token.signal()
public void signal() {
signal(node.getDefaultLeavingTransition(), new ExecutionContext(this));
//q里的getDefaultLeavingTransition()如果有多条\径,则去W一条\?br />
}
void signal(Transition transition, ExecutionContext executionContext) {
//省略其他代码
node.leave(executionContext, transition);
//省略其他代码
}
q里的node是刚才令牌所在的开始节点,我们来看看jbpm是如何将令牌从开始节点移C个节点的?br />
public void leave(ExecutionContext executionContext, Transition transition) {
Token token = executionContext.getToken();
token.setNode(this);//此时令牌q在开始节?br />
executionContext.setTransition(transition);
//略去部分代码
executionContext.setTransitionSource(this);
transition.take(executionContext);//实现令牌的{U?br />
}
我们来看看transition.take(..)Ҏ做了什?br />
public void take(ExecutionContext executionContext) {
//略去部分代码
to.enter(executionContext);//d开始节点,q入C个节?br />
}
大家可能会有点疑问,q个to节点是什么是否初始化的?其实在signal时有句node.getDefaultLeavingTransition()Q这句返回Transition对象Q该对象已l初始化了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);
}
在这D代码中的注释这句,真正实现了o牌从开始节点到下个节点了?br />
xQjbpm工作引擎的内部工作原理׃l完了,其实q就是工作流引擎最核心的部分了Q就是如何从一个环节{Ud另一个环节。或怽会说“q么单,我马上就可以写一?#8221;Q其实不Ӟ上面我们所用的例子是十分简单的例子Q其实在工作联盟规范中q有其他复杂的节Ҏ型,如splitQjoinQsubflow{。不q幸q的是这些复杂的节点模型jbpm都ؓ我们提供了他自己的默认的实现Q这些节Ҏ型都在org.jbpm.graph.node包下。jbpm引擎中很好的抽象了节Ҏ型Nodec,大部分的复杂节点模型都承自NodeQ我们也可以定制自己的节点,只要实现Nodecȝexecute()Ҏ卛_方便的实现。其实从上面分析的代码可以看出,NodecM要的逻辑处理是在leave()、enter()和execute()三个ҎQ大家可以看下ProcessStateQjoinQforkq些节点模型是如何实现的?br />
以上单介l了jbpm引擎内核的工作原理,如有不对的地方还望指正?br />