引言
Activiti 是一个轻量级、可扩展的开源工作流和业务流程管理(BPM)引擎,由 Alfresco 软件公司开发,基于 BPMN 2.0 标准。它广泛应用于企业级应用中,用于自动化业务流程,如请假审批、订单处理、合同签署等。Activiti 的核心优势在于其模块化设计、高性能和易于集成。本文将深入解析 Activiti 的源码架构与核心实现原理,帮助开发者理解其内部工作机制,从而更好地使用和扩展它。
Activiti 的源码托管在 GitHub 上,版本以 7.x 为主(最新稳定版为 7.1.0)。我们将基于 Activiti 7 的源码进行分析,重点关注其核心模块:引擎、流程定义、执行、历史记录和任务管理。文章将结合代码示例,详细说明关键类和方法的实现逻辑。
Activiti 源码架构概览
Activiti 的架构设计遵循分层和模块化原则,主要分为以下几个核心模块:
- Activiti Engine(引擎核心):负责流程的执行、状态管理和持久化。
- Activiti Modeler(建模器):提供 BPMN 2.0 图形化建模工具。
- Activiti REST API:提供 RESTful 接口,便于远程调用。
- Activiti UI(用户界面):基于 Angular 的前端界面,用于流程监控和任务处理。
- Activiti Cloud:支持云原生部署,集成 Kubernetes 和 Docker。
源码结构(基于 GitHub 仓库):
activiti-engine:核心引擎模块,包含流程定义、执行、历史等核心类。activiti-modeler:BPMN 2.0 模型解析和生成。activiti-rest:REST API 实现。activiti-common:公共工具类和配置。activiti-spring-boot-starter:Spring Boot 集成支持。
Activiti 依赖于 Spring Framework、MyBatis(或 JPA)和数据库(如 H2、MySQL、PostgreSQL)。其架构图如下(文字描述):
[用户/应用]
↓ (REST API / Spring Integration)
[Activiti Engine]
↓ (BPMN 解析 / 执行引擎)
[持久化层 (MyBatis/JPA)]
↓
[数据库 (ACT_* 表)]
Activiti 的核心设计思想是“流程即代码”,通过 BPMN 2.0 XML 定义流程,引擎负责解析并执行。源码中大量使用了设计模式,如工厂模式(ProcessEngineFactory)、策略模式(Command Pattern)和观察者模式(事件监听)。
核心模块详解
1. 流程定义(Process Definition)
流程定义是 Activiti 的起点,它将 BPMN 2.0 XML 转换为可执行的流程模型。核心类包括 BpmnModel、ProcessDefinition 和 Deployment。
源码分析
在 activiti-engine 模块中,org.activiti.engine.repository 包定义了流程定义相关接口。关键类 RepositoryService 是入口,用于部署和查询流程定义。
// 示例:部署 BPMN 文件
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("processes/leave-request.bpmn20.xml")
.deploy();
内部实现原理:
- BPMN 解析:Activiti 使用
org.activiti.bpmn.converter包中的解析器(如BpmnXMLConverter)将 XML 转换为BpmnModel对象。BpmnModel是内存中的流程模型,包含流程元素(如用户任务、网关、事件)。 - 持久化:部署时,引擎将
BpmnModel序列化为数据库表(如ACT_GE_BYTEARRAY存储 XML,ACT_RE_PROCDEF存储流程定义元数据)。 - 源码片段(简化版):
这里,// BpmnXMLConverter.java (org.activiti.bpmn.converter) public BpmnModel convertToBpmnModel(InputStream inputStream) { // 使用 SAX 解析器读取 XML SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); BpmnXMLParserHandler handler = new BpmnXMLParserHandler(); saxParser.parse(inputStream, handler); return handler.getBpmnModel(); }BpmnXMLParserHandler是一个自定义的 SAX 事件处理器,它根据 BPMN 2.0 规范映射 XML 元素到 Java 对象。例如,<userTask>元素被解析为UserTask类实例。
详细例子:假设一个请假流程的 BPMN XML:
<process id="leaveRequest" name="请假流程">
<startEvent id="start" />
<userTask id="approveTask" name="经理审批" activiti:assignee="manager" />
<sequenceFlow sourceRef="start" targetRef="approveTask" />
<endEvent id="end" />
</process>
解析后,BpmnModel 包含一个 Process 对象,其 getUserTasks() 方法返回 UserTask 列表。引擎通过 ProcessDefinitionEntity 将其持久化到数据库。
2. 流程执行(Process Execution)
流程执行是 Activiti 的核心,涉及流程实例的创建、任务分配和状态流转。核心类包括 Execution、ActivityInstance 和 ExecutionEntity。
源码分析
入口是 RuntimeService,用于启动流程实例。关键方法 startProcessInstanceByKey 启动一个流程实例。
// 示例:启动流程实例
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leaveRequest");
内部实现原理:
- 命令模式:Activiti 使用命令模式(
Command接口)封装所有操作。每个服务方法(如startProcessInstanceByKey)都会创建一个Command对象,并通过CommandExecutor执行。这确保了事务管理和线程安全。 - 执行树:流程实例由
ExecutionEntity表示,形成一个树状结构。每个活动(如用户任务)对应一个Execution。引擎使用ActivityBehavior接口定义活动的行为(如UserTaskActivityBehavior)。 - 持久化:执行状态存储在
ACT_RU_EXECUTION和ACT_RU_TASK表中。使用 MyBatis 进行 ORM 映射。 - 源码片段(简化版):
这里,// StartProcessInstanceCmd.java (org.activiti.engine.impl.cmd) public class StartProcessInstanceCmd implements Command<ProcessInstance> { public ProcessInstance execute(CommandContext commandContext) { // 1. 获取流程定义 ProcessDefinition processDefinition = commandContext.getProcessEngineConfiguration() .getRepositoryService().getProcessDefinition(processDefinitionId); // 2. 创建执行实体 ExecutionEntity execution = new ExecutionEntity(processDefinition); execution.setVariable("initiator", initiator); // 设置流程变量 // 3. 触发开始事件 execution.start(); // 4. 持久化 commandContext.getExecutionEntityManager().insert(execution); return execution; } }CommandContext提供了对引擎组件的访问,如ExecutionEntityManager。execution.start()方法会查找流程的开始事件(StartEvent),并执行其ActivityBehavior。
详细例子:在请假流程中,启动实例后,引擎会创建 ExecutionEntity,并将其状态设置为“活跃”。当遇到用户任务时,UserTaskActivityBehavior 会:
- 创建
TaskEntity并分配给指定用户(activiti:assignee="manager")。 - 将任务插入
ACT_RU_TASK表。 - 暂停执行,等待任务完成。
代码示例:自定义 ActivityBehavior(扩展点):
public class CustomUserTaskBehavior extends UserTaskActivityBehavior {
@Override
public void execute(ActivityExecution execution) {
// 自定义逻辑:检查用户权限
String assignee = (String) execution.getVariable("assignee");
if (!hasPermission(assignee)) {
throw new ActivitiException("无权限");
}
super.execute(execution); // 调用父类创建任务
}
}
在 BPMN 中通过 activiti:class 属性引用:<userTask activiti:class="com.example.CustomUserTaskBehavior" />。
3. 任务管理(Task Management)
任务管理涉及用户任务的创建、分配、完成和查询。核心类包括 Task、TaskService 和 TaskEntity。
源码分析
入口是 TaskService,用于操作任务。
// 示例:查询和完成任务
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().assignee("manager").list();
for (Task task : tasks) {
taskService.complete(task.getId()); // 完成任务,流程继续
}
内部实现原理:
- 任务生命周期:任务从创建(
TaskEntity插入数据库)到完成(更新状态并触发后续流程)。完成任务时,引擎会通知Execution继续执行下一个活动。 - 查询优化:
TaskQuery使用 MyBatis 动态 SQL 构建查询,支持条件过滤(如 assignee、dueDate)。 - 事件监听:任务事件(如创建、完成)可通过
EventListener监听,实现自定义逻辑。 - 源码片段(简化版):
// CompleteTaskCmd.java (org.activiti.engine.impl.cmd) public class CompleteTaskCmd implements Command<Void> { public Void execute(CommandContext commandContext) { // 1. 获取任务实体 TaskEntity task = commandContext.getTaskEntityManager().findById(taskId); // 2. 更新任务状态 task.setEndTime(new Date()); task.setDeleteReason("completed"); // 3. 通知执行实体继续 ExecutionEntity execution = task.getExecution(); execution.signal("complete", variables); // 触发信号,继续流程 // 4. 删除任务(从 ACT_RU_TASK) commandContext.getTaskEntityManager().delete(task); return null; } }execution.signal()方法会调用当前活动的signal方法,推动流程前进。
详细例子:在请假流程中,经理完成审批任务:
- 任务完成时,
CompleteTaskCmd会设置流程变量approved=true。 - 引擎根据 BPMN 中的序列流(
<sequenceFlow conditionExpression="${approved}" />)决定下一步:如果批准,跳转到结束事件;否则,跳转到“重新申请”任务。 - 代码示例:设置变量完成任务:
Map<String, Object> variables = new HashMap<>(); variables.put("approved", true); taskService.complete(taskId, variables); // 变量会传递到后续活动
4. 历史记录(History Management)
历史记录用于审计和监控,核心类包括 HistoricProcessInstance、HistoricTaskInstance 和 HistoryService。
源码分析
入口是 HistoryService,用于查询历史数据。
// 示例:查询历史流程实例
HistoryService historyService = processEngine.getHistoryService();
List<HistoricProcessInstance> historicInstances = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
.list();
内部实现原理:
- 事件记录:引擎在流程执行的关键点(如活动开始/结束、任务创建/完成)触发
HistoryEventHandler,将事件持久化到历史表(如ACT_HI_PROCINST、ACT_HI_TASKINST)。 - 级别配置:Activiti 支持历史级别(NONE、ACTIVITY、AUDIT、FULL),通过
historyLevel配置控制记录粒度。 - 源码片段(简化版):
这里,// HistoryEventProducer.java (org.activiti.engine.impl.history) public void recordActivityStart(ActivityExecution execution) { if (historyLevel.isAtLeast(HistoryLevel.ACTIVITY)) { HistoricActivityInstanceEntity activity = new HistoricActivityInstanceEntity(); activity.setActivityId(execution.getCurrentActivityId()); activity.setStartTime(new Date()); activity.setProcessInstanceId(execution.getProcessInstanceId()); // 插入 ACT_HI_ACTINST 表 historyManager.insert(activity); } }historyLevel是一个枚举,决定是否记录。
详细例子:在请假流程中,当经理开始审批任务时,引擎记录 HistoricActivityInstance,包括活动 ID、开始时间。查询时,可通过 HistoryService 获取完整审计 trail。
5. 事件与监听器(Events and Listeners)
Activiti 支持事件驱动架构,允许在流程执行中插入自定义逻辑。
源码分析
核心是 EventListener 接口和 ActivitiEvent 类型。
// 示例:添加任务创建监听器
processEngine.getRuntimeService().addEventListener(new ActivitiEventListener() {
@Override
public void onEvent(ActivitiEvent event) {
if (event.getType() == ActivitiEventType.TASK_CREATED) {
Task task = ((TaskEvent) event).getTask();
System.out.println("任务创建: " + task.getName());
}
}
});
内部实现原理:
- 事件类型:定义在
ActivitiEventType枚举中,如PROCESS_STARTED、TASK_COMPLETED。 - 触发机制:在命令执行前后,
CommandContext会发布事件到EventDispatcher。 - 源码片段(简化版):
监听器可以是全局的(通过配置)或任务/流程级别的(通过 BPMN 扩展属性)。// EventDispatcher.java (org.activiti.engine.impl.event) public void dispatchEvent(ActivitiEvent event) { for (EventListener listener : eventListeners) { if (listener.isFailOnException()) { listener.onEvent(event); } else { try { listener.onEvent(event); } catch (Exception e) { log.error("Event listener error", e); } } } }
详细例子:在 BPMN 中配置监听器:
<userTask id="approveTask">
<extensionElements>
<activiti:eventListener class="com.example.TaskCreateListener" event="create" />
</extensionElements>
</userTask>
监听器类实现 EventListener,在任务创建时发送通知邮件。
高级主题:扩展与优化
1. 自定义行为(Custom Behaviors)
Activiti 允许通过实现 ActivityBehavior 扩展引擎行为。例如,集成第三方服务。
public class ServiceTaskBehavior implements ActivityBehavior {
@Override
public void execute(ActivityExecution execution) {
// 调用外部 API
String result = callExternalService(execution.getVariable("input"));
execution.setVariable("output", result);
execution.signal(); // 继续流程
}
}
在 BPMN 中:<serviceTask activiti:class="com.example.ServiceTaskBehavior" />。
2. 性能优化
- 批量操作:使用
ManagementService的executeJob批量处理异步任务。 - 缓存:配置
ProcessEngineConfiguration的processDefinitionCache和taskCache。 - 数据库优化:使用索引(如
ACT_RU_TASK.ASSIGNEE_)和分页查询。
3. 与 Spring Boot 集成
Activiti 提供 Spring Boot Starter,简化配置。
// application.yml
spring:
activiti:
database-schema-update: true
history-level: full
// 启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Activiti 自动配置 ProcessEngine Bean,可通过 @Autowired 注入。
常见问题与调试
- 问题:流程卡在用户任务。
- 调试:检查
ACT_RU_TASK表,确认任务分配。使用ManagementService查看执行树:managementService.getExecutionTree(processInstanceId)。
- 调试:检查
- 问题:历史数据不完整。
- 解决:确保
historyLevel设置为AUDIT或FULL。
- 解决:确保
结论
Activiti 的源码架构体现了模块化、可扩展的设计理念,通过 BPMN 2.0 标准确保了流程的标准化。核心实现依赖于命令模式、事件驱动和持久化层,使其在企业级应用中高效可靠。理解这些原理有助于开发者自定义扩展、优化性能,并解决复杂业务场景。建议从源码仓库克隆项目,结合调试工具(如 IntelliJ IDEA)深入探索。参考官方文档(https://www.activiti.org/)和 GitHub 仓库获取最新更新。
