camunda el flow - modric2jeff/archive GitHub Wiki
核心组件
-
Expression Manager
ExpressionManager是 Camunda 引擎中负责表达式管理的顶层入口,负责创建各种类型的表达式对象(如值表达式ValueExpression、方法表达式MethodExpression)- 内部持有对底层表达式语言(默认为 JUEL,也可替换成 MVEL、Groovy 等)的配置和工厂引用
-
Expression Factory
- 对接具体表达式语言的工厂接口,例如 JUEL 的
ExpressionFactoryImpl - 负责将字符串形式的表达式解析并编译成可执行的表达式对象
- 对接具体表达式语言的工厂接口,例如 JUEL 的
-
Expression
-
通用接口,定义了
getValue(VariableScope scope)等方法 -
主要实现:
ValueExpression(读取变量、属性引用、算术运算等)MethodExpression(调用对象方法)
-
-
Variable Scope
VariableScope接口及其实现(如DelegateExecution、DelegateTask),为表达式求值提供上下文数据- 变量查找遵循层次:局部变量 → 父作用域变量 → 全局流程变量
-
ELContext & FunctionMapper
- 在 JUEL 中,通过
ELContext维护求值时的上下文环境(变量解析器、函数映射器、属性解析器等) - Camunda 扩展注册了自定义函数(如日期函数、XML 处理函数等)
- 在 JUEL 中,通过
总体架构
+-----------------------------------------------------------+
| Camunda Process Engine |
| |
| +------------------+ +------------------+ |
| | BPMN 解析 & 部署 | --> | BPMN 执行引擎 | |
| +------------------+ +------------------+ |
| | |
| v |
| +------------------+ |
| | ExpressionManager| |
| +------------------+ |
| | |
| +-------------------+----------------+ |
| | | |
| +----------------------+ +----------------------+ |
| | ExpressionFactory | | Variable Scopes | |
| +----------------------+ +----------------------+ |
| | | |
| v | |
| +---------------------+ | |
| | Parsed & Compiled | | |
| | Expression (AST) | | |
| +---------------------+ | |
| | | |
| v | |
| +---------------------+ | |
| | ELContext (JUEL) | | |
| +---------------------+ | |
| | | |
| v | |
| +---------------------+ | |
| | 求值(变量替换、调用)|<--- VariableScope ------+ |
| +---------------------+ |
+-----------------------------------------------------------+
表达式处理流程
-
解析阶段
- BPMN 文件或 API 中读取到字符串表达式(如
${order.amount * 0.1}) ExpressionManager.createExpression(String)调用底层ExpressionFactory.createValueExpression(...)- 字符串被解析成内部 AST(Abstract Syntax Tree)
- BPMN 文件或 API 中读取到字符串表达式(如
-
编译/缓存
- 对于相同文本的表达式,Camunda 会在
ExpressionManager级别进行缓存,避免重复解析 - AST 被保存在
ValueExpression对象中
- 对于相同文本的表达式,Camunda 会在
-
求值阶段
-
引擎执行到包含表达式的节点(如条件网关、任务属性、脚本任务等)时,调用
expression.getValue(variableScope) -
构造
ELContext,注入:- 当前
VariableScope(变量容器) - 自定义函数映射
- 属性解析器(用于处理点操作,如
foo.bar)
- 当前
-
JUEL Runtime 遍历 AST:
- 遇到变量名时,委托给
VariableMapper从VariableScope中读取 - 遇到运算符时,执行相应算术/逻辑运算
- 遇到方法调用时,通过
MethodExpression调用 Java 方法
- 遇到变量名时,委托给
-
最终返回计算结果
-
示例:求值流程演示
假设在某个用户任务的条件表达式中使用:
<sequenceFlow id="flow1"
sourceRef="task1"
targetRef="task2"
conditionExpression="${invoice.amount > 1000}" />
-
部署时
Expression conditionExpr = expressionManager.createExpression("${invoice.amount > 1000}"); // 解析为 ValueExpression,并缓存 AST -
执行时
// 假设 currentExecution 是 DelegateExecution,实现了 VariableScope boolean takeFlow = (Boolean) conditionExpr.getValue(currentExecution); -
内部求值步骤
-
构造
ELContext,绑定currentExecution -
AST 根节点为 “>” 运算
-
对左右子树求值:
-
左侧子树:解析
invoice.amount- 读取变量
invoice(一个 Java Bean 或 Map) - 通过属性解析器调用
getAmount()
- 读取变量
-
右侧子树:数字常量
1000
-
-
执行比较运算
>, 得到布尔结果 -
返回结果给流程引擎,决定流程走向
-
通过以上架构与流程,Camunda 7 的表达式引擎能够灵活地将 BPMN 中的动态逻辑与 Java 运行时数据无缝集成,支持复杂的条件判断、函数调用和脚本扩展。