1.Activiti整体架构
Activiti工作流引擎架构大致分为6层,如图所示。从上到下依次为工作流引擎层、部署层、业务接口层、命令拦截层、命令层和行为层。
-
工作流引擎层:主要指ProcessEngine接口,这是Activiti所有接口的总入口。
-
部署层:包括DeploymentBuilder和BpmnModel等与流程部署相关的类。理论上,部署层并不属于Activiti引擎架构的分层体系。将其单独拿出来作为一层,只是为了突出其重要性。流程运转基于流程定义,而流程定义解析就是流程的开始。从流程模型转换为流程定义、将其解析为简单Java对象(Plain Ordinary Java Object, POJO),都是基于部署层实现的。
-
业务接口层:面向业务提供各种服务接口,如RuntimeService、TaskService等。
-
命令拦截层:采用责任链模式,通过拦截器层为命令的执行创造条件,如开启事务、创建CommandContext上下文、记录日志等。
-
命令层:Activiti的业务处理层。Activiti的整体编码模式采用的是命令模式,将业务逻辑封装为一个个Command接口实现类。这样,新增一个业务功能时只需新增一个Command实现。
-
行为层:包括各种FlowNodeActivityBehavior和ActivitiEventListener,这些类负责执行和监听Activiti流程具体的流转动作。
2.Activiti设计模式
Activiti源码主要应用了命令模式、责任链模式和命令链模式,要更好地理解Activiti源码及其设计理念,有必要深入理解这3种设计模式
2.1 Activiti命令模式
Command(抽象命令类):抽象命令对象,可以根据不同的命令类型,写出不同的实现类。
-
ConcreteCommand(具体命令类):抽象命令对象的具体实现。
-
Invoker(调用者):请求的发送者,通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令之间存在关联。程序运行时,会调用命令对象的execute()方法,间接调用接收者的相关操作。
-
Receiver(接收者):接收者执行与请求相关的操作,是真正执行命令的对象,实现对请求的业务处理。
-
Client(客户端):在客户类中需要创建调用者对象、具体命令类对象,创建具体命令对象时需要指定对应的接收者。发送者和接收者之间不存在关联关系,均通过命令对象来调用。
Activiti命令模式UML结构图如图所示
Activiti中的每一个数据库的增、删、改、查操作,均为将一个命令的实现交给Activiti的命令执行者执行。Activiti使用一个CommandContext类作为命令接收者,该类维护一系列Manager对象,这些Manager对象类似J2EE中的数据访问对象(Data Access Object, DAO)。 在Activiti中构建的命令模式的类,主要包括以下5个部分。
- Command:抽象命令接口。该接口定义了一个execute()抽象方法,调用该方法时,需要传入参数CommandContext。
- CommandContext :命令上下文。CommandContext实例从Context获取,以栈的形式存储在使用本地线程的变量中(
ThreadLocal<Stack<CommandContext>>
)。 - CommandExecutor:命令执行者。该接口提供了两种方法执行命令,可以同时传入命令配置参数CommandConfig和Command,也可以只传入Command。
- ServiceImpl:Activiti的服务类,如TaskServiceImpl等,均继承ServiceImpl类。该类持有CommandExecutor对象,在该服务实现中,构造各个Command的实现类传递给CommandExecutor执行。这个类是命令的发送者,对应标准命令模式定义中的Client。
- CommandInterceptor:命令拦截器,有多个实现类。它被CommandExecutor实现类调用,是最终的
2.2 Activiti责任链模式
责任链模式有以下参与者。
- Handler(请求处理者接口):定义一个处理请求的接口,包含抽象处理方法和一个后继链。
- ConcreteHandler(请求处理者实现):请求处理接口的实现,它可以判断是否能够处理本次请求,如果可以处理请求就进行处理,否则就将该请求转发给它的后继者。
- Client (客户端):组装责任链,并向链头的具体对象提交请求。它不关心处理细节和请求的传递过程。 Activiti责任链模式UML结构图如图所示
Activiti责任链模式下的类主要有以下几种。
- CommandInterceptor:命令拦截器接口。它是采用命令模式实现的拦截器,作为责任链的"链节点"的定义,可以执行命令,也可以获取和设置下一个"链节点"。
- ProcessEngineConfigurationImpl:维护整条责任链的类,在该工作流引擎抽象实现类中,实现了对整条责任链的维护。
- CommandInvoker:CommandInterceptor责任链"链节点"实现类之一,负责责任链末尾节点的命令执行。
2.3 Activiti命令链模式
了解了Activiti命令模式和责任链模式后,可以发现Activiti命令链模式实质上就是命令模式和责任链模式结合的产物。Activiti命令链模式UML结构图如图所示。
在initCommandExecutor()方法中,先判断commandExecutor是否为null,只有当该对象为空时,才实例化命令执行器。Activiti实例化命令执行器时,将一系列命令拦截器作为参数,传递给initInterceptorChain()方法,组成了命令拦截器责任链,并返回责任链的开始节点,该操作是为了方便后续程序依次执行命令拦截器。Activiti根据命令配置对象defaultCommandConfig,以及命令拦截器责任链中开始节点实例化CommandExecutorImpl类,该类负责全局统筹命令拦截器的调用工作。