引言

Activiti 是一个轻量级、可扩展的开源工作流和业务流程管理(BPM)引擎,由 Alfresco 软件公司开发,基于 BPMN 2.0 标准。它广泛应用于企业级应用中,用于自动化业务流程,如请假审批、订单处理、合同签署等。Activiti 的核心优势在于其模块化设计、高性能和易于集成。本文将深入解析 Activiti 的源码架构与核心实现原理,帮助开发者理解其内部工作机制,从而更好地使用和扩展它。

Activiti 的源码托管在 GitHub 上,版本以 7.x 为主(最新稳定版为 7.1.0)。我们将基于 Activiti 7 的源码进行分析,重点关注其核心模块:引擎、流程定义、执行、历史记录和任务管理。文章将结合代码示例,详细说明关键类和方法的实现逻辑。

Activiti 源码架构概览

Activiti 的架构设计遵循分层和模块化原则,主要分为以下几个核心模块:

  1. Activiti Engine(引擎核心):负责流程的执行、状态管理和持久化。
  2. Activiti Modeler(建模器):提供 BPMN 2.0 图形化建模工具。
  3. Activiti REST API:提供 RESTful 接口,便于远程调用。
  4. Activiti UI(用户界面):基于 Angular 的前端界面,用于流程监控和任务处理。
  5. 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 会:

  1. 创建 TaskEntity 并分配给指定用户(activiti:assignee="manager")。
  2. 将任务插入 ACT_RU_TASK 表。
  3. 暂停执行,等待任务完成。

代码示例:自定义 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。
  • 源码片段(简化版):
    
    // 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 扩展属性)。

详细例子:在 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 仓库获取最新更新。