flowable之三 启动一个流程并跟踪

1. 背景介绍

当我们部署一个流程并启动后,Flowable会按照既定流程定义及进行节点处理以及自动流转,从一个节点执行到下一个节点,直至结束。在此过程中,系统如何处理BPMN XML文件?节点如何进行流转?本文对flowable内部源码进行解析,挖掘其引擎原理。

2. 系统原理

2.1. 总览图

总览图

在这里插入图片描述

如上图所示为流程启动关键节点图,主要由以下几部分组成:

1. 启动命令封装(橙色部分)

主要功能:通过将bpmnXML格式文件解析为程序可执行的内存对象Process。 类似于 saga 事件驱动中的 event 。。

a. 获取流程定义 ProcessDefinition(通过入参<流程key or 流程id>找到对应的流程定义)

b. 加载解析bpmn.xml文件(工作流原始文件)

c. 生成bpmnModel(工作流描述)

d. 生成Process(工作流执行)

2. 命令执行器(蓝色部分)

主要功能:流程执行过程中会添加各种拦截器,其中最为核心的是CommandInvokerInterceptor

a. LogInterceptor:当日志级别为debug时,会输出启动日志

b. SpringTransactionInterceptor

  Spring事务管理,用户事务的doTransaction、commit、rollback

c. CommandContextInterceptor:执行SqlSession close方法,将数据进行持久化

d. TransactionContextInterceptor

e. BpmnOverrideContextInterceptor

f. CommandInvokerInterceptor:真正执行启动流程命令的拦截器

3. 节点流转(绿色部分)

主要功能:完成对流程节点的执行,及找到下一个可执行的节点,直至流程运行完成。其最核心的包括DefaulFlowableEngineAgenda,该类持有operations,通过对节点操作封装为不同的Operation,进行节点的流转。

2.2. 命令执行器(CommandExecutor)

Flowable是通过命令模式 + 责任链模式完成对操作的执行,flowable启动代码中,构造ProcessEngine时会调用 init()方法进行引擎初始化,如下图所示:

2.3 启动命令封装

启动命令通过入参的流程key or 流程定义id加载对应的流程定义数据后,初始化了启动operation操作,其核心源码如下:

  1. 调用new StartProcessInstanceCmd 生成启动命令
    在这里插入图片描述

  2. StartProcessInstanceCmd.execute() 方法定义如下:其首先获取流程定义ProcessDefinition,之后通过调用startProcessInstance启动流程。

流程定义数据来源于数据表:ACT_RE_PROCDEF,其是在流程部署时写入的,注意其字段deploymentId,在作为数据表ACT_GE_BYTEARRAY的外键,关联了 流程XML原始文件
在这里插入图片描述

  1. 在得到流程定义后,通过调用 ProcessInstanceHelper#createProcessInstance方法进行流程启动,注意在该方法中,通过调用 ProcessDefinitionUtil.getProcess 得到流程 Process

注意在之后,通过 process.getInitialFlowElement 方法得到流程初始节点。在之后构造 Execution 实体时,设置该初始节点。
在这里插入图片描述
在这里插入图片描述

4)在方法 ProcessInstanceHelper.startProcessInstance 中,通过调用CommandContextUtil.getAgenda(commandContext).planContinueProcessOperation(execution) 将当前实例添加到操作堆栈operations中。

       至此:完成了启动命令的初始化过程

在这里插入图片描述

2.4流程节点流转(重点)

2.4.1 节点流转核心节点图

在这里插入图片描述

重点:上图为节点流转图,节点流转的核心是AbstractAgenda,其默认的实现是 DefaultFlowableEngineAgenda

该类持有变量operations,operations是个一个堆栈,在流转过程中,通过DefaultFlowableEngineAgenda一系列操作可以

将不同的操作压入栈中,然后运转过程中,将每一个操作弹出栈进行命令的执行。这里的operation指默认实现了AbstractOperation的操作类,AbstractOperation的实现类如下所示:

比如要继续流转,则压入ContinueProcessOperation,需要结束流程则需要压入 EndExecutionOperation。

在这里插入图片描述

2.4.2. ContinueProcessOperation操作

ContinueProcessOperation操作对节点和顺序流分别作了处理,如下图所示:

在这里插入图片描述
像极了 saga 中的 router 和 handler

当前元素为节点时,执行如下主要操作:

1)标记节点开始

2)执行节点监听器

3)获取节点对应行为器

4)执行行为器

当无对应的行为器时,则创建 takeOutgoingSequenceFlowsOperation 操作

在这里插入图片描述
当前元素为顺序流时,执行如下主要操作:

1)找到当前元素后置元素,设置为当前执行元素

2)如果后置元素是节点,则直接执行

3)如果后置元素是顺序流,则构造ContinueProcessOperation操作

在这里插入图片描述

2.4.2.1. 节点行为器ActivityBehavior

如下图所示为行为器的实现类,从图中可以看到我们熟悉的StartEvent、NoneEvent及ServiceTask的实现类。
在这里插入图片描述
在行为器执行完成对应操作后,由行为器决定是否继续向后流转节点FlowNodeActivityBehavior默认提供了leave()方法,其内部主要是构造 TakeOutgoingSequenceFlowsOperation 继续流转节点

2.4.3. TakeOutgoingSequenceFlowsOperation操作

TakeOutgoingSequenceFlowsOperation的实现分别对节点和顺序流进行了操作,如下图所示:
在这里插入图片描述

当前元素为节点时:
1)首先标记当前节点执行完成

2)遍历后置顺序流元素,并计算顺序流表达式属性

3)当无有效的后置顺序流元素时,则构建EndExecutionOperation,压入栈中

4)存在有效的后置顺序流元素时,则遍历顺序流并且构造 ContinueProcessOperation操作,压入栈中

在这里插入图片描述
当前元素为顺序流时:

1)标记当前元素结束,构造ContinueProcessOperation操作,压入栈中
在这里插入图片描述

2.5 Example

下面以该流程为例,详细列出操作流转步骤:
在这里插入图片描述

其节点流转图如下:

详细步骤如下:

Step 1: 在流程启动初期,operations堆栈中压入ContinueProcessOperation操作,传入的execution的当前节点为开始节点

在这里插入图片描述

Step 2: 取出栈顶操作元素开始节点并执,首先进行节点开始持久化操作,之后调用节点行为类执行,开始节点的行为类是 NoneStartEventActivityBehavior,如下图所示为空操作,

其并没有实现execute()方法,还是复用了父类FlowNodeActivityBehavior的execute()方法,执行leave方法,压入TakeOutgoingSequenceOperation操作,此时execution的当前节点为开始节点

Step 3: 弹出栈顶TakeOutgoingSequenceOperation(开始节点),首先进行节点结束持久化操作,之后获取开始节点的后置可用分支,压入ContinueProcessOperation堆栈,

此时execution的当前节点为 开始节点-创建变量节点顺序流

Step 4: 取出栈顶ContinueProcessOperation(开始节点-创建变量节点顺序流) 并执行,其目标节点为 创建变量节点,开始执行,首先执行节点开始持久化操作,接着执行其行为类JavaDelegate,

执行完成后,压入TakeOutgoingSequenceOperation操作,此时execution的当前节点为创建变量节点

计算节点后置节点以及其他逻辑后,压入操作类,此时execution的当前节点为开始节点–>创建变量的连线。

Step 5: 弹出栈顶TakeOutgoingSequenceOperation(创建变量节点),首先进行节点结束持久化操作,之后获取创建变量节点的可用分支,压入ContinueProcessOperation堆栈,

此时此时execution的当前节点为创建变量节点-结束事件顺序流

Step 6: 弹出栈顶ContinueProcessOperation(创建变量节点-结束事件),其目标节点为结束事件,开始执行,首先进行节点开始持久化操作,接着执行其行为类 NoneEndEventActivityBehavior,如下图可得,

在这里插入图片描述

结束事件行为器构造了TakeOutgoingSequenceOperation操作,此时execution的当前节点为

结束事件节点

Step 7: 弹出栈顶TakeOutgoingSequenceOperation(结束节点),首先进行节点结束持久化操作,之后获取创建变量节点的可用分支,无可用分支,则构造 EndExecutionOperation,此时execution的当前节点为结束节点
在这里插入图片描述

Step 8: 弹出栈顶EndExecutionOperation(结束节点),执行相关结束操作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/278284.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用于自动驾驶的基于深度学习的图像 3D 物体检测:综述

论文地址&#xff1a;https://ieeexplore.ieee.org/abstract/document/10017184/ 背景 准确、鲁棒的感知系统是理解自动驾驶和机器人驾驶环境的关键。自动驾驶需要目标的 3D 信息&#xff0c;包括目标的位置和姿态&#xff0c;以清楚地了解驾驶环境。 摄像头传感器因其颜色和…

Kubernetes 容器编排(2)

可视化部署 官方Dashboard 部署Dashboard # kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml # kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard # 注意将 type: ClusterIP 改为 type: NodePo…

消除非受检警告

在Java中&#xff0c;有一些情况下编译器会生成非受检警告&#xff08;Unchecked Warnings&#xff09;。这些警告通常与泛型、类型转换或原始类型相关。消除这些警告可以提高代码的可读性和安全性。以下是一些常见的非受检警告以及如何消除它们的例子&#xff1a; 1. 泛型类型…

数据库和数据仓库的区别

数据仓库是在数据库已知大量存在的前提下&#xff0c;为了进一步挖掘数据资源&#xff0c;为了决策需要产生的&#xff1b;数据仓库在设计的时候有意添加反范式设计&#xff0c;目的是提高查询效率 对比内容数据库数据仓库数据内容近期值历史的 归档的数据数据目标面向业务操作…

记录 | Microsoft Remote Desktop for mac安装

Microsoft Remote Desktop for mac安装 网上一些教程的下载安装老是跳转来跳转去&#xff0c;而且下载了的也不一定适用于 mac&#xff0c; 这里直接提供 Microsoft Remote Desktop for mac 的安装包的下载地址&#xff1a; microsoft-remote-desktop-for-mac

【TES720D-KIT】基于国内某厂商FMQL20S400全国产化ARM开发套件(核心板+底板)

板卡概述 TES720D-KIT是专门针对我司TES720D&#xff08;基于国内某厂商FMQL20S400的全国产化ARM核心板&#xff09;的一套开发套件&#xff0c;它包含1个TES720D核心板&#xff0c;加上一个TES720D-EXT扩展底板。 FMQL20S400是国内某厂商电子研制的全可编程融合芯片&#xf…

解决下载huggingface模型权重无法下载的问题

文章目录 方法一(推荐)方法二方法三依然存在的问题 由于某些原因&#xff0c;huggingface的访问速度奇慢无比&#xff0c;对于一些模型(比如大语言模型LLM)的权重文件动辄几十上百G&#xff0c;如果用默认下载方式&#xff0c;很可能中断&#xff0c;这里推荐几种方式。 方法一…

力扣题目学习笔记(OC + Swift) 12. 整数转罗马数字

12. 整数转罗马数字 罗马数字包含以下七种字符&#xff1a; I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&#xff0c; 罗马数字 2 写做 II &#xff0c;即为两个并列的 1。12 写做 XI…

Axure动态面板的应用与ERP系统登录界面、主页左侧菜单栏、公告栏的绘制

目录 一、动态面板 1.1 简介 1.2 使用动态面板的原因 二、动态面板之轮播图实现案例 2.1 完成步骤 2.2 最终效果 三、动态面版之多方式登录案例 四、动态面板之后台主界面左侧菜单栏 五、ERP登录界面 六、ERP主界面菜单栏 七、ERP公告栏 八、登录页面跳转公告栏 一…

【AntDesign】Modal模态窗带来的缓存问题

背景 : 使用antdesign modal写模态窗, 列表点击"编辑"可以打开模态窗, 并对里面的文字和图片进行修改 问题 : 每次关闭模态窗后, 点击其他数据进行修改, 会发现图片这栏有时候有数据, 有时候会为空, 明明已经传了imgUrl过来了。 modal模态窗具有缓存问题&#xff0…

SpringBoot 基础概念:SpringApplication#getSpringFactoriesInstances

SpringBoot 基础概念&#xff1a;SpringApplication#getSpringFactoriesInstances SpringApplication#getSpringFactoriesInstances SpringApplication#getSpringFactoriesInstances private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,…

Linux的文件系统 内核结构

Linux的文件系统 Q1&#xff1a;什么是文件系统&#xff1f; A&#xff1a;在学术的角度下&#xff0c;文件系统指“操作系统用于明确存储设备组织文件的方法”&#xff0c;是“文件管理系统”的简称&#xff0c;本质也是代码&#xff0c;一段程序 Q2&#xff1a;文件系统&…