【轉】通過jbpm源碼分析jbpm引擎內核工作原理

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引擎內核的工作原理,如有不對的地方還望指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章