Activiti提供了一組Service蔬蕊,向用戶暴露流程引擎的功能兰珍,Service內(nèi)部通過命令模式執(zhí)行真正的操作局齿。以RepositoryService
的流程部署方法deploy
為例:
public class RepositoryServiceImpl extends ServiceImpl implements RepositoryService {
...
public Deployment deploy(DeploymentBuilderImpl deploymentBuilder) {
return commandExecutor.execute(new DeployCmd<Deployment>(deploymentBuilder));
}
...
}
從代碼中可以看到deploy
方法執(zhí)行的是DeployCmd
,執(zhí)行命令的是一個叫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方法中執(zhí)行了真正的命令闹啦。
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
構(gòu)造成調(diào)用鏈,并用CommandExecutor
的first指針指向調(diào)用鏈的第一個CommandInterceptor
:
CommandExecutor的執(zhí)行
commandExecutor.execute(new DeployCmd<Deployment>(deploymentBuilder));
當(dāng)調(diào)用CommandExecutor
的execute
方法時窍奋,會調(diào)用first的execute
方法荐健,執(zhí)行CommandInterceptor
調(diào)用鏈:
public <T> T execute(CommandConfig config, Command<T> command) {
return first.execute(config, command);
}
以Activiti實現(xiàn)的LogInterceptor
為例,execute
方法中執(zhí)行了打日志的代碼后琳袄,會繼續(xù)執(zhí)行下一個CommandInterceptor
:
log.debug(...)
return next.execute(config, command);
最終在CommandInvoker
中會執(zhí)行Command
:
public <T> T execute(CommandConfig config, Command<T> command) {
return command.execute(Context.getCommandContext());
}
CommandExecutor擴展
在Activiti中江场,可以實現(xiàn)自己的CommandInterceptor
,在初始化ProcessEngine時加載到調(diào)用鏈中窖逗。例如Activiti在結(jié)合Spring時址否,就是通過實現(xiàn)自定義的事務(wù)CommandInterceptor
,在攔截器中開啟事務(wù)碎紊,調(diào)用next方法佑附。