小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

揭秘jbpm流程引擎內(nèi)核設(shè)計(jì)思想及構(gòu)架...

 夜郎 2007-09-06
揭秘jbpm流程引擎內(nèi)核設(shè)計(jì)思想及構(gòu)架
作者 胡長(zhǎng)城(銀狐999)
 
1     前言... 1
2.1      概念的基礎(chǔ)... 2
2.2      環(huán)境的基礎(chǔ)... 2
4.1      模型與定義對(duì)象... 4
4.2      調(diào)度機(jī)制與算法... 5
4.3      執(zhí)行機(jī)制與狀態(tài)... 5
4.4      實(shí)例對(duì)象與執(zhí)行環(huán)境... 5
6.1      首先解決如何形式化描述一個(gè)流程的問題... 6
6.2      抽象的節(jié)點(diǎn)(Node)和轉(zhuǎn)移(Transition... 7
6.3      流程:節(jié)點(diǎn)與轉(zhuǎn)移的組合... 7
6.4      節(jié)點(diǎn)的類型和擴(kuò)展... 8
7.1      吸納自Petri Net思想... 8
7.2      Token的推進(jìn)... 9
7.3      非常簡(jiǎn)單的調(diào)度機(jī)制... 11
8.1      執(zhí)行機(jī)制... 12
8.2      分支處理... 13
10       后記... 15
 

 

       流程引擎內(nèi)核僅是“滿足Process基本運(yùn)行”的最微小結(jié)構(gòu),而整個(gè)引擎則要復(fù)雜很多,包括“狀態(tài)存儲(chǔ)”、“事件處理”、“組織適配”、“時(shí)間調(diào)度”、“消息服務(wù)”等等外圍的服務(wù)性功能。引擎內(nèi)核,僅包含最基本的對(duì)象和服務(wù),以及用于解決流程運(yùn)行問題的調(diào)度機(jī)制和執(zhí)行機(jī)制。
       如果,你掌握了一個(gè)流程引擎的靈魂,你才有能力理解它的全部。否則,一個(gè)引擎對(duì)你來(lái)說(shuō),可能只是一個(gè)復(fù)雜的結(jié)構(gòu),豐富多彩API、令人眼花繚亂的“功能”和“服務(wù)”而已。
 
       本 身工作流這個(gè)領(lǐng)域就是一個(gè)很“狹窄”的領(lǐng)域,國(guó)內(nèi)的廠商也不是很多,其中有部分實(shí)現(xiàn)技術(shù)并不弱。但可能涉于安全等因素,并沒有多少技術(shù)人員探討“深度的工 作流技術(shù)實(shí)現(xiàn)問題”。而廣大的開發(fā)愛好者卻還在花費(fèi)大量的時(shí)間在摸索“如何理解工作流、如何應(yīng)用工作流”。 所以在此之前,國(guó)內(nèi)尚未有一篇技術(shù)文章探討工作流引擎內(nèi)核的實(shí)現(xiàn),當(dāng)然也沒有探討jBpm引擎內(nèi)核的文章了。在www. 技術(shù)站點(diǎn)和我的blog(http://blog.csdn.net/james999)上有幾篇專門探討jbpm應(yīng)用的文章,對(duì)于初步想了解如何使用jbpm的讀者來(lái)說(shuō),值得看看。
 
       對(duì)于這方面的技術(shù)分享,開源是個(gè)不錯(cuò)的突破口。
       本篇就是以jBpm為實(shí)例,來(lái)詮釋工作流引擎的內(nèi)核設(shè)計(jì)思路和結(jié)構(gòu)。但是這僅僅是從jBpm的實(shí)現(xiàn)角度來(lái)輔助大家理解,因?yàn)楣ぷ髁饕鎯?nèi)核的設(shè)計(jì)、實(shí)現(xiàn)是有很多方式:這會(huì)因所選的模型、調(diào)度算法、推進(jìn)機(jī)制、狀態(tài)變遷機(jī)制、執(zhí)行機(jī)制等多方面的不一樣,而會(huì)差別很大。比如基于Activity Diagram模型的jBpm和基于FSM模型的OSWorkflow引擎內(nèi)核之間就有很大的差別。
       相比較而言,jBpm的模型比較復(fù)雜,而引擎內(nèi)核實(shí)現(xiàn)的比較“精簡(jiǎn)”,非常便于大家“由淺入深的理解”。

2       閱讀本篇的基礎(chǔ)準(zhǔn)備

       本文的讀者群主要是面向有一定工作流基本概念的開發(fā)人員。所以本文認(rèn)為你已經(jīng)具備了如下基本工作流知識(shí):
(1)       初步了解工作流系統(tǒng)結(jié)構(gòu)。比如理解工作流引擎在工作流系統(tǒng)中所處的位置和作用
(2)       對(duì)流程定義(Process Definition)和流程實(shí)例(Process Instance)相關(guān)對(duì)象有所了解。比如理解Process Instance代表什么,工作項(xiàng)(WorkItem)代表什么。
       在閱讀本篇的時(shí)候,如果你已經(jīng)搭建了一套jbpm的開發(fā)環(huán)境,那么將有助于你更容易理解本篇的很多內(nèi)容,也便于實(shí)際體驗(yàn)代碼。從www.官方網(wǎng)站下載jbpm-starters-kit開發(fā)包,按照其參考手冊(cè),可以很容易在eclipse開發(fā)環(huán)境中建立項(xiàng)目,效果圖類似如下:

 

3       什么是流程引擎內(nèi)核?

       我比較推崇“微內(nèi)核的流程引擎構(gòu)架”,并在最近兩三年內(nèi)寫了兩篇探討此方面的文章:第一篇是寫于05年7月份的《微內(nèi)核流程引擎架構(gòu)體系》,第二篇是07年7月份的《微內(nèi)核過程引擎的設(shè)計(jì)思路和構(gòu)架》(受普元《銀彈》雜志約稿所寫,尚未對(duì)外公開)。
       但至今對(duì)外闡述引擎內(nèi)核到底是什么。
  
 
       正如上面的兩張圖所示,我們可以通過“微內(nèi)核”的構(gòu)架來(lái)使得流程引擎的結(jié)構(gòu)更加“清晰”。而能否實(shí)現(xiàn)“微內(nèi)核”的根本,則是看你是否能夠設(shè)計(jì)并抽象出“良好的引擎內(nèi)核結(jié)構(gòu)”。
 
       很顯然,要想設(shè)計(jì)出一套結(jié)構(gòu)優(yōu)良的引擎內(nèi)核,首要條件就是:明白什么是引擎內(nèi)核。
 
       首 先我們需要明白引擎是什么,引擎可以做什么。這在WfMC的《工作流參考模型》中已經(jīng)有很詳細(xì)的解答,本文不再重復(fù)。知道這個(gè)僅僅是不夠的,你還需要很清 晰的明白如何去“為流程建模”,而這則在Aalst大師所著的《工作流管理——模型、方法、系統(tǒng)》一書有細(xì)致闡述,本文也不再重復(fù)。
       但很可惜,至今尚未有一本專門的書籍來(lái)論述“過程建模方法”的,或者說(shuō)如何利用這些既有的“過程建模方法(諸如FSM、PetriNet、EPC、Activity Diagram等等)”來(lái)解決流程問題。這個(gè)只能分別查閱相關(guān)資料,此處也不敘述。
       因?yàn)槲谋局恢v“引擎內(nèi)核”。
 
       如果我們暫且把那復(fù)雜的流程業(yè)務(wù)性問題,諸如“組織模型分配”、“分支條件計(jì)算”、“事件處理”、“消息調(diào)度”、“工作項(xiàng)處理”、“存儲(chǔ)”、“應(yīng)用處理”、以及那些“變態(tài)的諸如會(huì)簽、回退之類的模型”都統(tǒng)統(tǒng)的拋棄,只留下“最單純的過程性問題”,也就是“解決一個(gè)過程運(yùn)行問題,按秩序的從一個(gè)節(jié)點(diǎn)到另一個(gè)節(jié)點(diǎn)的執(zhí)行”。——這就是引擎內(nèi)核所關(guān)注的根本問題。
       上面這句話,估計(jì)會(huì)引起很多人“拍磚”。在很多人看來(lái),工作流之所以看起來(lái)很“難”,就是因?yàn)檫@些復(fù)雜多變的“業(yè)務(wù)性問題”都統(tǒng)統(tǒng)綁在一個(gè)“引擎”上造成的。
       其 實(shí),這是兩個(gè)“維度”的問題,也就是“引擎的抽象”和“引擎的應(yīng)用”這兩個(gè)不同維度,不同層面的問題。但這絕不是兩個(gè)獨(dú)立的問題,“引擎的抽象”的好與 壞,直接影響到“引擎的應(yīng)用”的可復(fù)雜度和可支持度,當(dāng)然我們也不能否認(rèn),“引擎的應(yīng)用”問題也是一個(gè)很復(fù)雜的問題。但本文是站在“引擎的抽象”這個(gè)維度 來(lái)闡述問題的。對(duì)于“引擎的應(yīng)用”問題,可參考我的前作:2003年11月份的《工作流模型分析》、2003年12月份的《工作流授權(quán)控制模型》、 2004年7月份的《工作流系統(tǒng)中組織模型應(yīng)用解決方案》。
       也就是說(shuō),本文不是指導(dǎo)大家如何去“使用jbpm”,而是闡述“jbpm的引擎的內(nèi)核部分是如何構(gòu)建的”。但本文的主旨不是告訴大家“jBpm是如何設(shè)計(jì)引擎內(nèi)核的”,而是以jBpm為例,來(lái)介紹“引擎內(nèi)核”。
 
       引擎內(nèi)核所關(guān)注的是一個(gè)非常“抽象”層面的問題,而不同引擎關(guān)注的“一套完整的執(zhí)行環(huán)境”?;蛘呶覀兛梢赃@么來(lái)說(shuō),引擎內(nèi)核的職責(zé)是非常“精簡(jiǎn)”的:確保流程按照既有的定義,從一個(gè)節(jié)點(diǎn)運(yùn)行到另一個(gè)節(jié)點(diǎn),并正確執(zhí)行當(dāng)前節(jié)點(diǎn)。
       總的來(lái)說(shuō),引擎內(nèi)核主要關(guān)注四個(gè)方面的問題:
(1)       流程定義問題:不是說(shuō)如何圖形化的定義流程,而是如何用一套定義對(duì)象,來(lái)詮釋所定義的流程。
(2)       流程調(diào)度問題:提供什么的機(jī)制,可以確保流程能夠處理復(fù)雜的“流程圖結(jié)構(gòu)”,諸如串行、并行、分支、聚合等等,并在這復(fù)雜結(jié)構(gòu)中確保流程從一個(gè)節(jié)點(diǎn)運(yùn)行到另一個(gè)節(jié)點(diǎn)。
(3)       流程執(zhí)行問題:當(dāng)流程運(yùn)行到某個(gè)節(jié)點(diǎn)的時(shí)候,需要一套機(jī)制來(lái)解決:是否執(zhí)行此節(jié)點(diǎn),并如何執(zhí)行此節(jié)點(diǎn)的問題,并維持節(jié)點(diǎn)狀態(tài)生命周期。
(4)       流程實(shí)例對(duì)象:需要一整套流程實(shí)例對(duì)象來(lái)描述流程實(shí)例運(yùn)行的狀態(tài)和結(jié)果。

       工作流引擎本身就是一種“base on model”的組件,流程實(shí)例的執(zhí)行都是依賴于所定義的“流程定義”,而工作流引擎則是提供了這樣一種環(huán)境,來(lái)維持流程實(shí)例的運(yùn)行。
       所以引擎內(nèi)核,必須提供一套定義對(duì)象來(lái)描述“流程定義”,并且這些定義對(duì)象必須反映出一種“模型”。
       比如jBpm的定義對(duì)象,是與其所基于的Activity Diagram模型相對(duì)應(yīng)的。

       引擎內(nèi)核的另一個(gè)重要功能,就是保證流程實(shí)例準(zhǔn)確的從一個(gè)節(jié)點(diǎn)運(yùn)行到另一個(gè)節(jié)點(diǎn),而這則需要依賴于一套調(diào)度機(jī)制。
       引擎的調(diào)度機(jī)制有很多種實(shí)現(xiàn)方法,有的甚至是與“所依賴的模型有關(guān)”。但普遍來(lái)講,很多引擎都受到Petri Net的影響,而采用token來(lái)調(diào)度。
       jBpm本身就吸納的token這套機(jī)制,當(dāng)然,與Petri Net的調(diào)度機(jī)制還是有所區(qū)別。我們將在下面的章節(jié)詳細(xì)介紹。

       經(jīng)過引擎的調(diào)度,實(shí)例運(yùn)行到某個(gè)節(jié)點(diǎn)了,此時(shí)必須必須提供一套機(jī)制,來(lái)判斷當(dāng)前節(jié)點(diǎn)是否可執(zhí)行,如果可執(zhí)行,那么需要提供一套runtime envrioment來(lái)執(zhí)行節(jié)點(diǎn)——這就是引擎的執(zhí)行機(jī)制。
       復(fù)雜的流程引擎會(huì)依賴于“流程實(shí)例狀態(tài)”或“活動(dòng)實(shí)例狀態(tài)”的約束和變遷來(lái)進(jìn)行處理。之所有有時(shí)候我們會(huì)把一個(gè)流程引擎也叫做“狀態(tài)機(jī)”,很大程度上也是這個(gè)原因。

       每個(gè)一個(gè)流程實(shí)例,必須維護(hù)一套屬于自己的“運(yùn)行環(huán)境和數(shù)據(jù)”,而這則是實(shí)例對(duì)象的責(zé)任了?;旧蠈?shí)例對(duì)象會(huì)包含如下信息:
(1)       與流程實(shí)例的狀態(tài)或控制信息
(2)       與活動(dòng)實(shí)例的狀態(tài)或控制信息。如果某些引擎不支持活動(dòng)實(shí)例,那么必然會(huì)有某些其他實(shí)例信息,可以當(dāng)前節(jié)點(diǎn)的狀或控制信息。
(3)       一些臨時(shí)的“執(zhí)行”信息,便于引擎針對(duì)某種情況進(jìn)行處理
 

 5       jbpm,“精簡(jiǎn)”的開源流程引擎

       好 的開源工作流引擎不多,jbpm和osworkflow算是其中兩個(gè)有特色而且比較容易實(shí)際應(yīng)用的。目前一些國(guó)內(nèi)的中小型流程應(yīng)用項(xiàng)目,就是在jbpm或 osworkflow的基礎(chǔ)上擴(kuò)展實(shí)現(xiàn)。jBpm采用了Activity Diagram的模型,而osworkflow則是FSM的模型。
       當(dāng)然,這僅僅是jbpm3之后的事情。自從被Jboss收購(gòu)之后,jbpm對(duì)早先的2.0構(gòu)架進(jìn)行了重組,整個(gè)結(jié)構(gòu)完全本著“微內(nèi)核”的思想進(jìn)行設(shè)計(jì)。
       現(xiàn)在這里從技術(shù)角度來(lái)分析jbpm3的優(yōu)點(diǎn),簡(jiǎn)單羅列幾個(gè)大家都容易看見的:
(1)       jbpm的模型是采用UML Activity Diagram的語(yǔ)義,所以便于開發(fā)人員理解流程。
(2)       jbpm提供了可擴(kuò)展的Event-Action機(jī)制,來(lái)輔助活動(dòng)的擴(kuò)展處理。
(3)       jbpm提供了靈活的條件表達(dá)式機(jī)制,來(lái)輔助條件解析、腳本計(jì)算的處理。
(4)       jbpm提供了可擴(kuò)展的Task及分配機(jī)制,來(lái)滿足復(fù)雜人工活動(dòng)的處理。
(5)       借助hibernate的ORM的優(yōu)勢(shì),jbpm能夠很容易支持多種數(shù)據(jù)庫(kù)。
 
當(dāng)然,還有一些優(yōu)點(diǎn),是很多開發(fā)人員并不太注意的,比如:
(1)       jbpm的Node機(jī)制非常靈活,開發(fā)人員可以很容易定制“業(yè)務(wù)化語(yǔ)義的節(jié)點(diǎn)”,并滿足運(yùn)行時(shí)候處理的需要。
 
有很多靈活的優(yōu)點(diǎn),當(dāng)然也少不了存在一些“局限”。
(1)       很顯然,只能有一個(gè)start-state。
(2)       jbpm依靠Token來(lái)調(diào)度和計(jì)算,在同一個(gè)時(shí)刻中,一個(gè)ProcessInstance只允許一個(gè)Token對(duì)象只存在一個(gè)Node中(分支當(dāng)然用Child Token對(duì)象處理)。所以本質(zhì)上就不支持“multi-instance”模式。
(3)       jbpm作為一款開源的工作流引擎,其更多的是關(guān)注“如何輔助你更容易的讓流程運(yùn)行完成”,但是并不記錄“流程運(yùn)行的歷史和軌跡”。這一點(diǎn)可能是東西方文化的差異性所在,因?yàn)閲?guó)內(nèi)的流程應(yīng)用,比較關(guān)注“運(yùn)行軌跡”。
 
       至 于其他的一些局限,比如不支持“回退”、“跳轉(zhuǎn)”等操作,這也是因?yàn)闁|西方文化的差異所在。西方人認(rèn)為“往回流轉(zhuǎn)的情況肯定也是一種業(yè)務(wù)規(guī)則所定義,那么 肯定可以通過分支或條件來(lái)解決”,而東方則把“回退作為一個(gè)人性化管理和處理的潛在特點(diǎn)”。所以諸如此類的一些“特定需求”,估計(jì)只能通過擴(kuò)展jbpm來(lái) 實(shí)現(xiàn)了,甚至有時(shí)候,簡(jiǎn)單的擴(kuò)展是無(wú)法解決問題的——正如上一節(jié)所說(shuō)的那樣,“引擎的抽象”會(huì)影響“引擎的應(yīng)用”的復(fù)雜度支持。
       但是,當(dāng)你試圖修改jbpm代碼的時(shí)候,你會(huì)顧慮jbpm的LGPL協(xié)議嗎?(很多國(guó)內(nèi)企業(yè)從來(lái)不考慮這個(gè)協(xié)議問題,寒)。
 

 6       jBpm流程模型與定義對(duì)象

       這里說(shuō)的“定義流程”并不是說(shuō)jbpm3中那個(gè)基于eclipse plugin的圖形化建模工具。而是如何去解決“形式化的描述一個(gè)流程”的問題。
       形 式化的描述流程并不是一個(gè)簡(jiǎn)單的問題,從上世紀(jì)七十開始,人們就在探索用各種各樣多的模型來(lái)描繪流程:Petri Net, FSM, EPC, Activity Diagram, 以及近來(lái)的XPDL MetaModel等等,延伸到如今的BPEL,BPMN,BPMD等等。
        jBpm采 用了Activity Diagram的模型語(yǔ)義:其將用Start State、State、Action State(Task Node)、End State、Fork、Join、Decision、Merge、Process State這幾個(gè)“元素”的組合來(lái)描述任何一個(gè)流程。其中Action State是Activity Diagram中的標(biāo)準(zhǔn)語(yǔ)義,在jBpm為了便于大家理解和使用,jBpm采用了TaskNode這個(gè)語(yǔ)義。
 
       在WfMC的Workflow Reference Model中,對(duì)流程引擎的功能描述,其中就包含一項(xiàng):解析流程定義。如果想滿足這這功能,前提條件就必須有最基本的兩個(gè):
(1)       有一套形式化的描述語(yǔ)言(通常為xml格式)。利用這個(gè)描述語(yǔ)言可以描述一個(gè)流程的定義。比如WfMC所提出的XPDL這個(gè)描述語(yǔ)言。當(dāng)然,jBpm也有自己的一套,名為jPDL,也是一個(gè)xml格式的。
(2)       有一套對(duì)象集可以反映流程的定義模型和結(jié)果,一般叫做定義對(duì)象。流程引擎就需要把“xml格式的流程定義”解析為一套對(duì)象,而這套對(duì)象的結(jié)構(gòu)則反映了流程的結(jié)構(gòu)。
      
       我們暫且不去探討jPDL那個(gè)形式化的xml語(yǔ)言,而把重心放在jBpm那套定義對(duì)象中。因?yàn)檫@個(gè)定義對(duì)象是屬于Engine Kernel的一部分。
6.2    抽象的節(jié)點(diǎn)(Node)和轉(zhuǎn)移(Transition
       面向?qū)ο蟮睦^承性、多態(tài)性可以讓我們從最抽象的部分來(lái)描述對(duì)象。那么這套定義對(duì)象也需要從最基礎(chǔ)的“抽象”說(shuō)起。
       process的本質(zhì)就是“節(jié)點(diǎn)”和“有向弧”,當(dāng)然你也可以說(shuō)是Node和Link,或者Node和Transition,或者Activity和Transition等等之類的。jBpm采用的是Node和Transition來(lái)表示“節(jié)點(diǎn)”和“有向弧”。
       于是乎,在jbpm中你可以看到這樣的結(jié)構(gòu)關(guān)系:
       對(duì)于一個(gè)節(jié)點(diǎn)來(lái)說(shuō),從定義角度,其只關(guān)心幾個(gè)事情:
(1)       這是個(gè)什么類型的節(jié)點(diǎn)。這個(gè)節(jié)點(diǎn)可能是start state,也可能是一個(gè)task node,或者是一個(gè)fork。
(2)       這個(gè)節(jié)點(diǎn)的轉(zhuǎn)入Transition和轉(zhuǎn)出Transition。
       可 能有的人會(huì)說(shuō),還需要關(guān)心節(jié)點(diǎn)的轉(zhuǎn)入轉(zhuǎn)出的類型,比如And Splite或者Xor Join之類。這個(gè)并沒有錯(cuò),因?yàn)楹芏嗔鞒棠P偷墓?jié)點(diǎn)元素需要考慮這個(gè),比如WfMC的XPDL模型。但是jBpm的節(jié)點(diǎn)是沒有這樣的屬性的,或者說(shuō)的更 準(zhǔn)確些,是Activity Diagram模型的節(jié)點(diǎn)沒有這樣的特性?;顒?dòng)圖是采用“Fork”、“Join”這樣的節(jié)點(diǎn)來(lái)解決“分支”問題。
       僅利用節(jié)點(diǎn)和轉(zhuǎn)移的組合,就可以表達(dá)一個(gè)“過程(Process)”。當(dāng)然這個(gè)流程只能告訴人們“大概的業(yè)務(wù)過程”,當(dāng)然不包括很復(fù)雜的信息。如下圖所示:
       這是一張非常標(biāo)準(zhǔn)的“活動(dòng)圖”,如果我們用jbpm的設(shè)計(jì)器,看看這樣一張“流程圖”:
 
       不論你如何繪畫,改變不了這張圖的本質(zhì):它就只有兩個(gè)基本元素:節(jié)點(diǎn)和轉(zhuǎn)移。只是有的節(jié)點(diǎn)是start-state,有的是task-node,有的是join,有的是end state而已。
       我 們可以通過定義自己的Node節(jié)點(diǎn)對(duì)象,來(lái)補(bǔ)充jbpm自定的節(jié)點(diǎn)對(duì)象。只需要extends Node,并重寫讀寫xml的read和write方法,重寫負(fù)責(zé)執(zhí)行的execute方法,在 org/jbpm/graph/node/node.types.xml中配置即可,當(dāng)然,你可以寫的更加復(fù)雜,更加業(yè)務(wù)化的節(jié)點(diǎn)。

7       jBpm的過程調(diào)度機(jī)制

       jBpm的過程調(diào)度機(jī)制是吸納了Petri Net的一些思想。
       jBpm采用Token來(lái)表示當(dāng)前實(shí)例運(yùn)行的位置,也利用token在流程各個(gè)點(diǎn)之間的轉(zhuǎn)移來(lái)表示流程的推進(jìn),如下圖所示:
 
       當(dāng)jbpm試圖去啟動(dòng)一個(gè)流程的時(shí)候,首先是構(gòu)造一個(gè)流程實(shí)例,并為此流程實(shí)例創(chuàng)建一個(gè)Root Token,并把這個(gè)Root Token放置在Start Node上。
       以下截取部分代碼實(shí)現(xiàn),僅供參考。手頭有jbpm3相應(yīng)開發(fā)環(huán)境的朋友,可以打開ProcessInstance和Token這兩個(gè)類。(注:以下所有參考代碼,為了突出主題,都已經(jīng)將實(shí)際代碼中的event,log等處理刪除)
public ProcessInstance( ProcessDefinition processDefinition ) {
    this.processDefinition = processDefinition;
    this.rootToken = new Token(this);
 
public Token(ProcessInstance processInstance) {
    this.processInstance = processInstance;
    this.node = processInstance.getProcessDefinition().getStartState();
       jbpm是允許在start-state執(zhí)行Task的,也允許在start-state創(chuàng)建工人任務(wù)。不過此處我們不予討論。
7.2    Token的推進(jìn)
       當(dāng)Token已經(jīng)在Start-State節(jié)點(diǎn)了,我們可以開始往前推進(jìn),來(lái)促使流程實(shí)例往前運(yùn)行。對(duì)于外部操作來(lái)說(shuō),觸發(fā)流程實(shí)例往下運(yùn)行的操作有兩個(gè):
(1)       強(qiáng)制執(zhí)行ProcessInstance的signal操作
(2)       執(zhí)行TaskInstance的end操作。
但是,這兩個(gè)操作,都是通過“當(dāng)前token的signal操作”來(lái)內(nèi)部實(shí)現(xiàn)的,如下圖所示:
 
       TokenSignal操作表示:實(shí)例需要離開當(dāng)前token所在的節(jié)點(diǎn),轉(zhuǎn)移到下一個(gè)節(jié)點(diǎn)上。因?yàn)?/span>NodeNode之間是“Transition”這個(gè)橋梁,所以,在轉(zhuǎn)移過程中,會(huì)首先把Token放入相關(guān)連的Transtion對(duì)象中,再由Transition對(duì)象把Token交給下一個(gè)節(jié)點(diǎn)。

       讓我們來(lái)看看Token類中signal方法的部分代碼實(shí)現(xiàn),僅供參考:
public void signal() {
    //注意ExecutionContext對(duì)象
    signal(node.getDefaultLeavingTransition(), new ExecutionContext(this));
}

void signal(Transition transition, ExecutionContext executionContext) {
    // start calculating the next state
    node.leave(executionContext, transition);
}
 
       接下來(lái),請(qǐng)注意node.leave()這個(gè)操作。這是一個(gè)很有意思的語(yǔ)義轉(zhuǎn)換:我們是采用token的signal操作來(lái)表示往下一個(gè)節(jié)點(diǎn)推進(jìn),但是實(shí)際確實(shí)執(zhí)行的node.leave ()操作。
 
       如果這地方讓你自己來(lái)實(shí)現(xiàn),代碼會(huì)不會(huì)就是這樣子呢?不妨此處想一想。
//假設(shè)代碼,僅供思考
void signal(Transition transition, ExecutionContext executionContext) {
    transition.take(executionContext);
}
 
       前 面說(shuō)過,jbpm的調(diào)度機(jī)制吸納的Petri Net的思想。在Petri Net中,并沒有transition中駐留token這個(gè)語(yǔ)義,token只駐留在庫(kù)所(Place)中。所以,jbpm此處的設(shè)計(jì)思路,是于此有一定 關(guān)系的。所以只是把一個(gè)ExecutionContext對(duì)象放在了transition中,而不是一個(gè)token對(duì)象。
       讓我們來(lái)看看node對(duì)象的leave方法:
public void leave(ExecutionContext executionContext, Transition transition) {
    Token token = executionContext.getToken();
    token.setNode(this);
    executionContext.setTransition(transition);
    executionContext.setTransitionSource(this);
    transition.take(executionContext);
}
              我們直接跟蹤進(jìn)Transition的take操作:
public void take(ExecutionContext executionContext) {
    executionContext.getToken().setNode(null);
    // pass the token to the destinationNode node
    to.enter(executionContext);
}
             
       經(jīng)過這么多的中間步驟,我們終于把ExecutionContext對(duì)象從一個(gè)node轉(zhuǎn)移到下一個(gè)node了。讓我們來(lái)看看Node對(duì)象的enter操作:
public void enter(ExecutionContext executionContext) {
    Token token = executionContext.getToken();
    token.setNode(this);
    // remove the transition references from the runtime context
    executionContext.setTransition(null);
    executionContext.setTransitionSource(null);
 
    // execute the node
    if (isAsync) {
     
    } else {
      execute(executionContext);
    }
}
 
       至此,jBpm成功的從一個(gè)節(jié)點(diǎn)轉(zhuǎn)移到下一個(gè)節(jié)點(diǎn)了?!?這就是jbpm的調(diào)度機(jī)制。
       怎么樣,是不是非常的簡(jiǎn)單?
       讓我們把整個(gè)過程,用一張更清晰的“思維圖”來(lái)展示一下:


8       jBpm的過程執(zhí)行機(jī)制

       前面我們的“過程調(diào)度機(jī)制”是為了讓流程可以正確的從“一個(gè)節(jié)點(diǎn)轉(zhuǎn)移到下一個(gè)節(jié)點(diǎn)”,而本節(jié)所要講解的jbpm“執(zhí)行機(jī)制”,則是為提供一個(gè)運(yùn)行機(jī)制,來(lái)保證“節(jié)點(diǎn)的正確執(zhí)行”。
       首先我們需要明確如下的概念:
(1)       節(jié)點(diǎn)有很多中,每種節(jié)點(diǎn)的執(zhí)行方式肯定是不一樣的
(2)       節(jié)點(diǎn)有自己的生命周期,不同的生命周期階段,所處的狀態(tài)不同。
 
       在WfMC的《工作流參考模型》文檔中,為活動(dòng)實(shí)例歸納了幾個(gè)可參考的生命周期。(僅供參考,實(shí)際很多工作流引擎的節(jié)點(diǎn)的生命周期要比這復(fù)雜)
 
       但是,jbpm并沒有突出“節(jié)點(diǎn)生命周期”這個(gè)理念,僅僅只是在“Event”中體現(xiàn)出出來(lái)。在我看來(lái),可能的原因有兩個(gè):
(1)       jBpm沒有NodeInstance這個(gè)概念。利用Token和TaskInstance,jBpm足以持久化足夠的信息,能夠讓流程實(shí)例迅速定位到當(dāng)前運(yùn)行的狀態(tài)。
(2)       jBpm的Event已經(jīng)很豐富,并且這個(gè)Event是圍繞“Token的轉(zhuǎn)移”而設(shè)置的,并不是圍繞Node的生命周期設(shè)置的。
(3)       通常我們需要在Active和Completed的生命周期內(nèi)所要操作的分支與聚合,在jBpm模型中分別由Fork、Join之類的節(jié)點(diǎn)替代。所以jBpm過分關(guān)注Node生命周期的管理意義不是非常大。
 
       作 為個(gè)人,我并不行賞jBpm這樣拋棄“節(jié)點(diǎn)生命周期管理”的實(shí)現(xiàn)方式,更行賞OBE(最早的基于XPDL模型的java工作流引擎之一)的生命周期約束和 管理。但是,也不得不承認(rèn),jBpm規(guī)避了“繁瑣的狀態(tài)維護(hù)”,反而讓處理變得“簡(jiǎn)易”,也更容易被大家所理解和接受,而這也正是OBE逐漸消失的一個(gè)原 因:過于復(fù)雜和臃腫。
      
      
讓我們?cè)谇懊婺菑坖Bpm的“調(diào)度機(jī)制思維圖”上,再稍稍補(bǔ)充一點(diǎn)(為了突出顯示,與上圖有所改動(dòng))。

       這張圖應(yīng)該可以很好的詮釋出,jBpm是如何執(zhí)行各種節(jié)點(diǎn)的,這也是得益于OO的“多態(tài)與繼承”特性。
 
       jBpm的執(zhí)行機(jī)制非常簡(jiǎn)單,但還是需要稍微補(bǔ)充一下有關(guān)“分支”方面的處理。
       jBpm采用sub token的機(jī)制來(lái)解決分支方面的處理:當(dāng)遇到有分支的時(shí)候,會(huì)為每個(gè)分支節(jié)點(diǎn)創(chuàng)建一個(gè)child token。在聚合節(jié)點(diǎn)(Join或Merge),則依賴其同步或異步的聚合方式,來(lái)分別處理。
       比如我們參看Fork節(jié)點(diǎn)的執(zhí)行代碼(為了突出重點(diǎn),省略部分代碼):
public void execute(ExecutionContext executionContext) {
    Token token = executionContext.getToken();
    Iterator iter = transitionNames.iterator();
    while (iter.hasNext()) {
      String transitionName = (String) iter.next();
      forkedTokens.add(createForkedToken(token, transitionName));
    }
    iter = forkedTokens.iterator();
    while( iter.hasNext() ) {
      //省略部分代碼
      ExecutionContext childExecutionContext = new ExecutionContext(childToken);
      leave(childExecutionContext, leavingTransitionName);
    }
}
 
protected ForkedToken createForkedToken(Token parent, String transitionName) {
    Token childToken = new Token(parent, getTokenName(parent, transitionName));
    forkedToken = new ForkedToken(childToken, transitionName);
    return forkedToken;

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       至于Merge節(jié)點(diǎn),我想此處不用在累贅的展示,有興趣的,可以參看Merge類的execute方法,即可。
 

9       jBpm內(nèi)核結(jié)構(gòu)與實(shí)例對(duì)象

       Jbpm引擎內(nèi)核的結(jié)構(gòu)非常“精簡(jiǎn)”。除了我們上面所說(shuō)的那些定義對(duì)象(各種Node節(jié)點(diǎn)和Transtion),還有幾個(gè)與“運(yùn)行實(shí)例”相關(guān)的對(duì)象。如下圖所示,jbpm引擎內(nèi)核對(duì)象主要是在org.jbpm.graph.def和org.jbpm.graph.exe包。
(1)       我們需要描述一個(gè)流程實(shí)例,所以需要一個(gè)ProcessInstance對(duì)象。
(2)       每個(gè)流程實(shí)例,都會(huì)維護(hù)一套屬于其自己的“執(zhí)行環(huán)境”,也就是ExecutionContext對(duì)象。注意,這里是一套,而不是一個(gè)。
 

10   后記

       上 半年寫了些bpm和SOA的文章,也被csdn的好友拉著忽悠了不少這方面的概念,弄的好像我開始搞這方面的工作似的。其實(shí)不然,本質(zhì)工作與這有“天壤之 別”,完全是非常底層的java技術(shù)應(yīng)用。而workflow,也有兩三年沒有從事這方面的開發(fā)了,所以寫此篇文章,著實(shí)費(fèi)了點(diǎn)功夫。
       想痛痛快快寫篇有關(guān)“引擎內(nèi)核”的文章,這個(gè)想法由來(lái)以及了,卻擔(dān)心自己不足以詮釋清楚,反而容易誤導(dǎo)他人,遂中途多次放棄。
       正如前面所說(shuō)的那樣,引擎內(nèi)核的實(shí)現(xiàn),并沒有一套“固定的模式”或者“固定的實(shí)現(xiàn)體系”,會(huì)因?yàn)楹芏嘁蛩囟斐蓪?shí)現(xiàn)不同。如果想把“引擎內(nèi)核”的實(shí)現(xiàn)真正詮釋清楚,必須把這些相關(guān)因素都詮釋明朗——但這依然是一個(gè)浩大的工程。
       前些日子,受朋友所托,為他們的公司學(xué)員講了幾節(jié)工作流的課程,期間嘗試jBpm來(lái)詮釋了一下引擎的實(shí)現(xiàn)思路,發(fā)現(xiàn)效果不錯(cuò)。——受此引發(fā),遂萌發(fā)了以jBpm為實(shí)例,來(lái)簡(jiǎn)單詮釋“流程引擎內(nèi)核”想法。
       耗時(shí)一周的業(yè)余時(shí)間,雖然還很難詮釋自己的全部想法,但“點(diǎn)出幾個(gè)要點(diǎn)”,還是應(yīng)該有了。
 
                                                                                           胡長(zhǎng)城
                                                                                           寫于2007年9月2日星期日 夜。
本文揭秘了jbpm引擎內(nèi)核的設(shè)計(jì)思想和構(gòu)架,但不是jbpm引擎的全部。請(qǐng)注意是“流程引擎內(nèi)核”,而不是“流程引擎”。如果我們把流程引擎比作工作流系統(tǒng)的“發(fā)動(dòng)機(jī)”,那么“引擎內(nèi)核”則是一個(gè)引擎的“靈魂”。

 ====================================================================
聲明:本文首發(fā)csdn blog,轉(zhuǎn)載請(qǐng)注明作者信息及原文地址,謝謝

作者信息:
胡長(zhǎng)城(銀狐999)
TIBCO中國(guó)研發(fā)中心 Infrastructure Team
http://www.
http://blog.csdn.net/james999
=====================================================================

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多