當(dāng)我們部署一個(gè)流程并啟動(dòng)之后,流程就會(huì)按照流程的定義進(jìn)行節(jié)點(diǎn)處理以及自動(dòng)流轉(zhuǎn)眉踱,從一個(gè)節(jié)點(diǎn)流向下一個(gè)節(jié)點(diǎn)裂逐,直至結(jié)束,并且在此過程中完成數(shù)據(jù)庫中各種表的數(shù)據(jù)更新。那么在這個(gè)過程中逊桦,activiti引擎是如何進(jìn)行流程的運(yùn)轉(zhuǎn)的呢眨猎?
在流程運(yùn)轉(zhuǎn)過程中的核心是:
-
ActivitiEngineAgenda
默認(rèn)實(shí)現(xiàn)DefaultActivitiEngineAgenda
該類持有變量:
private static final Logger logger = LoggerFactory.getLogger(DefaultActivitiEngineAgenda.class);
protected LinkedList<Runnable> operations = new LinkedList();
protected CommandContext commandContext;
其中最關(guān)鍵的地方就是operations,operations是一個(gè)隊(duì)列强经,在流程開始運(yùn)轉(zhuǎn)的過程中睡陪,通過ActivitiEngineAgenda的一系列實(shí)現(xiàn)可以將不同需要執(zhí)行操作按照順序壓入棧中,然后運(yùn)轉(zhuǎn)過程中再將每一個(gè)操作彈出進(jìn)行命令的執(zhí)行。何為操作呢宝穗?上述operations中存放的元素的實(shí)現(xiàn)類為AbstractOperation的子類户秤,AbstractOperation持有執(zhí)行 實(shí)例execution,以便對當(dāng)前execution進(jìn)行操作逮矛。AbstractOperation的實(shí)現(xiàn)如下圖
比如要繼續(xù)運(yùn)轉(zhuǎn)流程鸡号,則向operations中壓入ContinueProcessOperation,要結(jié)束流程則壓入EndExecutionOperation须鼎。在每一個(gè)操作完成的時(shí)候鲸伴,將接下來要執(zhí)行的操作壓入operations棧中,這樣就達(dá)到了流程運(yùn)轉(zhuǎn)的效果晋控。
-
CommandInvoker
該類是一個(gè)命令調(diào)用類汞窗,查看執(zhí)行操作的方式:
protected void executeOperations(CommandContext commandContext) {
while(!commandContext.getAgenda().isEmpty()) {
Runnable runnable = commandContext.getAgenda().getNextOperation();
this.executeOperation(runnable);
}
}
-
ActivityBehavior
活動(dòng)行為類,每一個(gè)節(jié)點(diǎn)都有行為類赡译,主要完成關(guān)于該節(jié)點(diǎn)的一些操作仲吏,比如對于開始節(jié)點(diǎn),開始節(jié)點(diǎn)一般沒有什么操作蝌焚,它的行為自然就是離開當(dāng)前節(jié)點(diǎn)裹唆;當(dāng)節(jié)點(diǎn)為userTask,則在該行為類中為userTask分配處理人等等只洒。連線是沒有行為類的
這里的方式邏輯其實(shí)就是實(shí)現(xiàn)了上述當(dāng)operations的元素不為空時(shí)许帐,從operations堆棧中彈出并執(zhí)行,直到operations中沒有操作為止毕谴。
下面以該流程為例:
1成畦、在流程啟動(dòng)初期,operations堆棧中壓入 ContinueProcessOperation操作涝开,傳入的execution的當(dāng)前節(jié)點(diǎn)為startEvent
2循帐、進(jìn)入CommandInvoker的executeOperations方法,取出隊(duì)列頭部操作元素并執(zhí)行忠寻。
3惧浴、調(diào)用this.commandContext.getHistoryManager().recordActivityStart(this.execution);進(jìn)行節(jié)點(diǎn)開始持久化,之后調(diào)用開始節(jié)點(diǎn)的行為類執(zhí)行奕剃,執(zhí)行完畢壓入TaskOutgoingSequenceOperation操作類衷旅。
4、彈出TaskOutgoingSequenceOperation執(zhí)行纵朋。調(diào)用this.commandContext.getHistoryManager().recordActivityEnd(this.execution, (String)null);進(jìn)行節(jié)點(diǎn)結(jié)束的持久化柿顶,計(jì)算節(jié)點(diǎn)出線以及其他邏輯后,壓入ContinueProcessOperation操作類操软,此時(shí)execution的當(dāng)前節(jié)點(diǎn)為startEvent-->userTask的連線嘁锯。
5、彈出ContinueProcessOperation執(zhí)行。執(zhí)行相關(guān)邏輯家乘,獲取連線的目標(biāo)節(jié)點(diǎn)并設(shè)置為當(dāng)前執(zhí)行實(shí)例的當(dāng)前節(jié)點(diǎn)蝗羊,并壓入ContinueProcessOperation操作類,此時(shí)執(zhí)行實(shí)例的當(dāng)前節(jié)點(diǎn)為userTask
6仁锯、彈出ContinueProcessOperation執(zhí)行耀找。獲取用戶任務(wù)行為類對userTask進(jìn)行處理,返回业崖,之后再?zèng)]有操作類可以彈出后野芒,判斷還有可執(zhí)行的執(zhí)行實(shí)例,則壓入ExecuteInactiveBehaviorsOperation操作類執(zhí)行双炕。
到這里流程運(yùn)轉(zhuǎn)結(jié)束狞悲,程序退出。
那么如果我們想要繼續(xù)使流程進(jìn)行運(yùn)轉(zhuǎn)妇斤,則要完成用戶任務(wù)摇锋。
基于上述原理我們可以很容易的對activiti功能進(jìn)行擴(kuò)展,比如節(jié)點(diǎn)任意跳轉(zhuǎn)趟济。