Activiti命令拦截器和设计模式
Activiti命令拦截器和设计模式 Activiti命令拦截器和责任链设计模式使用场景每个对流程的操作都可以看成一个命令command,Activiti会对每个命令进行拦截处理,Activiti的命令拦截用到了命令模式和责任链模式,命令模式的本质在于将命令进行封装,发出命令和执行命令分离;职责链模式只需要将请求放入职责链上,其处理细节和传递都不需要考虑;执行入口commandExecutor是命令执行的入口。在命令来临时,service会调用commandExecutor的execute方法,例如runtimeService。所以commandExecutor是命令执行的第一步。那么Activiti是什么时候给service注入commandExecutor的呢?在ProcessEngineConfigurationImpl中init方法中会initServices,其又在初始化的时候注入commandExecutor,源码如下:public void initServices() initService(repositoryService); initService(runtimeService); initService(historyService); initService(identityService); initService(taskService); initService(formService); initService(managementService); initService(dynamicBpmnService); public void initService(Object service) if (service instanceof ServiceImpl) (ServiceImpl) service).setCommandExecutor(commandExecutor);/注入了commandExecutor 命令模式的表现上面分析了命令执行的第一步,就是调用CommandExecutor.execute方法,然后我们跟踪去看这个execute方法,在子类CommandExecutorImpl中看到了实际的调用。protected CommandInterceptor first;/拦截器Override public <T> T execute(CommandConfig config, Command<T> command) return first.execute(config, command);/实际调用的是拦截器的execute方法 然后我们对比命令模式的几个特性:1. 将命令进行封装Activiti封装成了Command对象;2. 命令发出者和执行者分离Activiti将任务最重交给了CommandInterceptor(CommandInvoker)来执行,而不是直接让CommandExecutor执行,就是命令模式解耦的体现。责任链模式的表现 & 拦截器顺序在ProcessEngineConfigurationImpl中init方法中会initCommandExecutor,其中指定了第一个拦截器。public void initCommandExecutor() if (commandExecutor = null) CommandInterceptor first = initInterceptorChain(commandInterceptors); /指定first commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first); 对于整个拦截器链的设置在initCommandInterceptors中。public void initCommandInterceptors() if (commandInterceptors = null) commandInterceptors = new ArrayList<CommandInterceptor>(); if (customPreCommandInterceptors != null) commandInterceptors.addAll(customPreCommandInterceptors);/自定义前置拦截器 commandInterceptors.addAll(getDefaultCommandInterceptors();/默认拦截器 if (customPostCommandInterceptors != null) commandInterceptors.addAll(customPostCommandInterceptors);/自定义后置拦截器 commandInterceptors.add(commandInvoker);/最后的是commanInvoker 我们再看看默认拦截器的设置,默认拦截器:log->transaction->context。public Collection<? extends CommandInterceptor> getDefaultCommandInterceptors() List<CommandInterceptor> interceptors = new ArrayList<CommandInterceptor>(); interceptors.add(new LogInterceptor();/日志拦截器 CommandInterceptor transactionInterceptor = createTransactionInterceptor(); if (transactionInterceptor != null) interceptors.add(transactionInterceptor);/事务拦截器 if (commandContextFactory != null) /上下文拦截器 interceptors.add(new CommandContextInterceptor(commandContextFactory, this); if (transactionContextFactory != null) interceptors.add(new TransactionContextInterceptor(transactionContextFactory); return interceptors; 我们再看看拦截器里面到底是做了什么,以log拦截器为例。public <T> T execute(CommandConfig config, Command<T> command) if (!log.isDebugEnabled() / do nothing here if we cannot log return next.execute(config, command); log.debug("n"); log.debug("- starting -", command.getClass().getSimpleName(); try return next.execute(config, command); finally log.debug("- finished -", command.getClass().getSimpleName(); log.debug("n"); 我们需要关注的就是return next.execute(config, command);这行代码,这也就是这个责任链执行的过程,每次都执行next的execute,直到没有next(commandInvoker)。在CommandInvoker的execute方法中,最后是执行了传入的command的execute方法,就是具体命令的方法,各种service都是通过这种方式来运行各自具体的命令。整个拦截器链调用过程如下: -全文完-