Activiti工作流学习笔记(四)——工作流引擎中责任链模式的建立与应用原理 (3)

直接debug到这里,可以看到,总共有4个拦截器对象,按照顺序排,包括LogInterceptor,CommandContextInterceptor,TransactionContextInterceptor,CommandInvoker(在命令模式里,该类相当Invoker角色)。这四个拦截器对象在责任链模式当中充当了具体处理者(Concrete Handler)角色。

image

责任链模式里剩余客户类(Client)角色应该是命令执行器this.commandExecutor。

因此,工作流引擎当中的责任链模式结构图如下:

image

组成一条拦截器链如下图所示——

image

生成拦截器链后,会返回一个(CommandInterceptor)chain.get(0),即拦截器LogInterceptor,为什么只返回第一个拦截器呢,这是一个很巧妙的地方,因为该拦截器里已经一层一层地嵌套进其他拦截器了,因此,只需要返回第一个拦截器,赋值给first即可。

接下来,就会创建命令执行器——

this.commandExecutor = new CommandExecutorImpl(this.getDefaultCommandConfig(), first);

这个命令执行器是整个引擎的底层灵魂,通过它,可以实现责任链模式与命令模式——

拦截器链初始化介绍完成后,接下来开始介绍拦截器链在引擎里的应用方式。


三、Activiti工作流里责任链模式的应用

Activiti引擎的各操作方法其底层基本都是以命令模式来实现的,即调用上面创建的命令执行器this.commandExecutor的execute方法来实现的,例如自动生成28张数据库表的方法,就是通过命令模式去做具体实现的——

this.commandExecutor.execute(processEngineConfiguration.getSchemaCommandConfig(), new SchemaOperationsProcessEngineBuild());

进入到commandExecutor方法里,会发现前边new CommandExecutorImpl(this.getDefaultCommandConfig(), first)建立命令执行器时,已将配置对象和嵌套其他拦截器的LogInterceptor拦截器对象,通过构造器CommandExecutorImpl(CommandConfig defaultConfig, CommandInterceptor first)生成对象时,传参赋值给了相应的对象属性,其中first引用指向LogInterceptor,即拦截器链上的第一个拦截器——

public class CommandExecutorImpl implements CommandExecutor { protected CommandConfig defaultConfig; protected CommandInterceptor first; public CommandExecutorImpl(CommandConfig defaultConfig, CommandInterceptor first) { this.defaultConfig = defaultConfig; this.first = first; } public CommandInterceptor getFirst() { return this.first; } public void setFirst(CommandInterceptor commandInterceptor) { this.first = commandInterceptor; } public CommandConfig getDefaultConfig() { return this.defaultConfig; } public <T> T execute(Command<T> command) { return this.execute(this.defaultConfig, command); } public <T> T execute(CommandConfig config, Command<T> command) { return this.first.execute(config, command); } }

当引擎执行this.commandExecutor.execute(xxx,xxx))类似方法时,其实是执行了this.first.execute(config, command)方法,这里的this.first在构建命令执行器时是通过LogInterceptor传进来的,因此,执行代码其实是调用了LogInterceptor内部的execute()方法,也就是说,开始拦截器链上的第一个LogInterceptor拦截器传递方法execute()请求——

image

进入到拦截器链上的第一个拦截器LogInterceptor。

根据其内部代码可以看出,这是一个跟日志有关的拦截器,内部并没有多少增强功能,只是做了一个判断是否需要debug日志打印。若需要,则进行debug打印,若不需要,直接进入到 if (!log.isDebugEnabled()) 为true的作用域内部,进而执行this.next.execute(config, command)用以将请求传递给下一个拦截器做处理。

public class LogInterceptor extends AbstractCommandInterceptor { private static Logger log = LoggerFactory.getLogger(LogInterceptor.class); public LogInterceptor() { } public <T> T execute(CommandConfig config, Command<T> command) { if (!log.isDebugEnabled()) { return this.next.execute(config, command); } else { log.debug("\n"); log.debug("--- starting {} --------------------------------------------------------", command.getClass().getSimpleName()); Object var3; try { var3 = this.next.execute(config, command); } finally { log.debug("--- {} finished --------------------------------------------------------", command.getClass().getSimpleName()); log.debug("\n"); } return var3; } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwywdy.html