ACTIVITI 源码研究之命令模式执行
2017-05-03 10:38
956 查看
流程引擎所有的操作都采用命令模式,使用命令执行器进行执行,命令执行器是一个采用拦截器链式执行模式。
-
命令执行器:CommandExecutor
其实现类CommandExecutorImpl的代码:
获取拦截器列表
拦截器列表的初始化在ProcessEngineConfigurationImpl中的initCommandExecutors();进行的
初始化拦截器列表:客户自定义前置拦截器、默认拦截器、后置拦截器
activiti默认的拦截器
初始化命令执行器
初始化命令拦截器链
在执行拦截器链执行的关键代码,它会调用下一个CommandInterceptor的execute方法。
最后会调用CommandInvoker的execute方法,执行真正的命令,完成整个命令的周期
我们以启动流程命令为例,探讨RuntimeService如何进行命令的执行。
值得注意的是commandExecutor是如何注入RuntimeService的呢。
在RuntimeServiceImpl 的基类ServiceImpl 存在commandExecutor属性。
我们在ProcessEngineConfigurationImpl的 init()方法中可以看出,在初始化命令执行器后,进行了服务的初始化,而RuntimeService在其中。
服务的初始化
Runtime服务的初始化,将命令执行器set进runtimeService中
-
命令执行器:CommandExecutor
其实现类CommandExecutorImpl的代码:
public class CommandExecutorImpl implements CommandExecutor { private final CommandConfig defaultConfig; private final CommandInterceptor first; //构造一个命令执行器 public CommandExecutorImpl(CommandConfig defaultConfig, CommandInterceptor first) { this.defaultConfig = defaultConfig; this.first = first; } ... //执行器执行一个命令 public <T> T execute(Command<T> command) { return execute(this.defaultConfig, command); } //开始拦截器的链式调用 public <T> T execute(CommandConfig config, Command<T> command) { return this.first.execute(config, command); } }
获取拦截器列表
拦截器列表的初始化在ProcessEngineConfigurationImpl中的initCommandExecutors();进行的
protected void initCommandExecutors() { initDefaultCommandConfig(); initSchemaCommandConfig(); //命令调用器 initCommandInvoker(); //初始化命令拦截器 initCommandInterceptors(); //初始化命令执行器 initCommandExecutor(); }
初始化拦截器列表:客户自定义前置拦截器、默认拦截器、后置拦截器
protected void initCommandInterceptors() { if (this.commandInterceptors == null) { this.commandInterceptors = new ArrayList(); if (this.customPreCommandInterceptors != null) { //客户自定义前置拦截器 this.commandInterceptors.addAll(this.customPreCommandInterceptors); } //默认拦截器 this.commandInterceptors.addAll(getDefaultCommandInterceptors()); if (this.customPostCommandInterceptors != null) { //后置拦截器 this.commandInterceptors.addAll(this.customPostCommandInterceptors); } //命令调用器,拦截器最后的一个,为调用具体的命令 this.commandInterceptors.add(this.commandInvoker); } }
activiti默认的拦截器
protected Collection<? extends CommandInterceptor> getDefaultCommandInterceptors() { List interceptors = new ArrayList(); //添加一个日志拦截器 interceptors.add(new LogInterceptor()); //添加一个事务控制拦截器 CommandInterceptor transactionInterceptor = createTransactionInterceptor(); if (transactionInterceptor != null) { interceptors.add(transactionInterceptor); } //CommandContext拦截器,进行命令的保存 interceptors.add(new CommandContextInterceptor(this.commandContextFactory, this)); return interceptors; }
初始化命令执行器
protected void initCommandExecutor() { if (this.commandExecutor == null) { //初始化命令拦截器链,并返回第一个拦截器 CommandInterceptor first = initInterceptorChain(this.commandInterceptors); //初始化命令执行器 this.commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first); } }
初始化命令拦截器链
protected CommandInterceptor initInterceptorChain(List<CommandInterceptor> chain) { if ((chain == null) || (chain.isEmpty())) { throw new ActivitiException(new StringBuilder().append("invalid command interceptor chain configuration: ") .append(chain).toString()); } //构建拦截器链,即上一个拦截器中存放着下一个拦截器 for (int i = 0; i < chain.size() - 1; ++i) { ((CommandInterceptor) chain.get(i)).setNext((CommandInterceptor) chain.get(i + 1)); } return ((CommandInterceptor) chain.get(0)); }
在执行拦截器链执行的关键代码,它会调用下一个CommandInterceptor的execute方法。
this.next.execute(config, command)
最后会调用CommandInvoker的execute方法,执行真正的命令,完成整个命令的周期
public class CommandInvoker extends AbstractCommandInterceptor { public <T> T execute(CommandConfig config, Command<T> command) { return command.execute(Context.getCommandContext()); } ... }
我们以启动流程命令为例,探讨RuntimeService如何进行命令的执行。
public class RuntimeServiceImpl extends ServiceImpl implements RuntimeService { public ProcessInstance startProcessInstanceByKey(String processDefinitionKey) { return ((ProcessInstance) this.commandExecutor .execute(new StartProcessInstanceCmd(processDefinitionKey, null, null, null))); af50 } .... }
值得注意的是commandExecutor是如何注入RuntimeService的呢。
在RuntimeServiceImpl 的基类ServiceImpl 存在commandExecutor属性。
我们在ProcessEngineConfigurationImpl的 init()方法中可以看出,在初始化命令执行器后,进行了服务的初始化,而RuntimeService在其中。
protected void init() { ... initCommandExecutors(); initServices(); ... }
服务的初始化
protected void initServices() { ... initService(this.runtimeService); ... }
Runtime服务的初始化,将命令执行器set进runtimeService中
protected void initService(Object service) { if (service instanceof ServiceImpl) ((ServiceImpl) service).setCommandExecutor(this.commandExecutor); }
相关文章推荐
- ACTIVITI 源码研究之命令模式执行
- ACTIVITI 源码研究之命令模式执行
- ACTIVITI 源码研究之命令模式执行
- OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式
- Android设计模式系列(7)--SDK源码之命令模式
- MySQL 从接收连接到执行连接命令的一个源码流程
- 实现一个模拟CMD.exe命令编辑模式执行与显示的Delphi控件
- SA 沙盘模式下不用恢复xp_cmdshell和xplog70.dll也执行命令
- OpenJDK源码研究笔记(六)--观察者模式工具类(Observer和Observable)和应用示例
- 实现一个模拟CMD.exe命令编辑模式执行与显示的Delphi控件
- linux下源码编译mysql在执行configure命令时出错
- 基于设计模式的学习之旅-----命令模式(附源码)
- 实例源码:利用Java调用可执行命令
- c# 在命令行模式中执行命令
- 用Thinkphp写的简单程序在命令行执行(非 Thinkphp 下的cli模式 而是php下的命令模式)
- 利用源码编译Android系统可执行命令
- 实例源码3:利用Java调用可执行命令并取得其返回值
- 实例源码2:利用Java调用可执行命令并取得其返回值
- 命令模式下的java带包及类的的编译及执行(error出现找不到符号)
- PureMVC学习系列-从源码深度剖析PureMVC(从PureMVC中看设计模式-Command命令模式) .