Activiti之CommondExecutor
Activiti提供了一组Service,向用户暴露流程引擎的功能,Service内部通过命令模式执行真正的操作。以RepositoryService
的流程部署方法deploy
为例:
public class RepositoryServiceImpl extends ServiceImpl implements RepositoryService {
...
public Deployment deploy(DeploymentBuilderImpl deploymentBuilder) {
return commandExecutor.execute(new DeployCmd<Deployment>(deploymentBuilder));
}
...
}
从代码中可以看到deploy
方法执行的是DeployCmd
,执行命令的是一个叫commandExecutor
的对象,这个对象从哪里来?有什么功能?
CommandExecutor的初始化
Activiti在初始化流程引擎ProcessEngine时,初始化了CommandExecutor对象:
public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfiguration {
...
//初始化方法
protected void init() {
...
initCommandExecutors();
...
}
//初始化CommandExecutor
protected void initCommandExecutors() {
...
initCommandInvoker();
initCommandInterceptors();
initCommandExecutor();
}
...
}
从初始化代码中可以看到,CommandExecutor的初始化分为3部分:Invoker
Interceptor
Executor
。
从上图中可以看到,CommondInvoker
是CommandInterceptor
的子类,CommandInvoker
不能指定next值,execute方法中执行了真正的命令。
public class CommandInvoker extends AbstractCommandInterceptor {
@Override
public <T> T execute(CommandConfig config, Command<T> command) {
return command.execute(Context.getCommandContext());
}
...
@Override
public void setNext(CommandInterceptor next) {
throw new UnsupportedOperationException("CommandInvoker must be the last interceptor in the chain");
}
}
在initCommandExecutor
方法中,会将CommandInteceptor
和CommandInvoker
构造成调用链,并用CommandExecutor
的first指针指向调用链的第一个CommandInterceptor
:
CommandExecutor的执行
commandExecutor.execute(new DeployCmd<Deployment>(deploymentBuilder));
当调用CommandExecutor
的execute
方法时,会调用first的execute
方法,执行CommandInterceptor
调用链:
public <T> T execute(CommandConfig config, Command<T> command) {
return first.execute(config, command);
}
以Activiti实现的LogInterceptor
为例,execute
方法中执行了打日志的代码后,会继续执行下一个CommandInterceptor
:
log.debug(...)
return next.execute(config, command);
最终在CommandInvoker
中会执行Command
:
public <T> T execute(CommandConfig config, Command<T> command) {
return command.execute(Context.getCommandContext());
}
CommandExecutor扩展
在Activiti中,可以实现自己的CommandInterceptor
,在初始化ProcessEngine时加载到调用链中。例如Activiti在结合Spring时,就是通过实现自定义的事务CommandInterceptor
,在拦截器中开启事务,调用next方法。