首页 > 代码库 > activiti源码分析(一)设计模式
activiti源码分析(一)设计模式
对activiti有基本了解的朋友都知道,activiti暴露了七个接口来提供工作流的相关服务,这些接口具体是如何实现的呢?查看源码发现其实现的形式大体如下:
public class RuntimeServiceImpl extends ServiceImpl implements RuntimeService { public ProcessInstance startProcessInstanceByKey(String processDefinitionKey) { return commandExecutor.execute(new StartProcessInstanceCmd<ProcessInstance>(processDefinitionKey, null, null, null)); } public ProcessInstance startProcessInstanceByKey(String processDefinitionKey, String businessKey) { return commandExecutor.execute(new StartProcessInstanceCmd<ProcessInstance>(processDefinitionKey, null, businessKey, null)); } ...}
service中的大部分方法都是通过调用commandExecutor.execute()完成的,然而点进去看则会发现什么都没有:
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 CommandInterceptor getFirst() { return first; } @Override public CommandConfig getDefaultConfig() { return defaultConfig; } @Override public <T> T execute(Command<T> command) { return execute(defaultConfig, command); } @Override public <T> T execute(CommandConfig config, Command<T> command) { return first.execute(config, command); }}
看到这里就会发现并不能看出这条语句究竟做了什么,那么究竟是如何提供服务的呢?其实activiti中大部分操作都是基于设计模式中的命令模式完成的(这里还使用了职责链模式,构造了命令拦截器链,用于在命令真正被执行之前做一系列操作)。下面结合源码详细介绍一下这些设计思路:
activiti的命令模式可能与我之前看的命令模式有所不同,命令模式的本质在于将命令进行封装,发出命令和执行命令分离。职责链模式只需要将请求放入职责链上,其处理细节和传递都不需要考虑。activiti将这两个模式整合在一起,构成了其服务主要的实现方式。其核心只有三个部分:CommandExecutor(命令执行器,用于执行命令),CommandInterceptor(命令拦截器,用于构建拦截器链),Command(命令自身)。这三个接口是整个核心的部分,还会涉及到其它的关键类,之后会一一说明,这三个类都在activiti-engine.jar这个activiti实现的核心包下,具体位置是:org.activiti.engine.impl.interceptor。下面由这三个接口逐步介绍相关的类和具体实现:
三个接口源码:
public interface Command <T> { T execute(CommandContext commandContext); }
/** * The command executor for internal usage. */public interface CommandExecutor { /** * @return the default {@link CommandConfig}, used if none is provided. */ CommandConfig getDefaultConfig(); /** * Execute a command with the specified {@link CommandConfig}. */ <T> T execute(CommandConfig config, Command<T> command); /** * Execute a command with the default {@link CommandConfig}. */ <T> T execute(Command<T> command); }
public interface CommandInterceptor { <T> T execute(CommandConfig config, Command<T> command); CommandInterceptor getNext(); void setNext(CommandInterceptor next);}
Command的接口中只有一个execute方法,这里才是写命令的具体实现,而CommandExecutor的实现类在上面已经给出,其包含了一个CommandConfig和一个命令拦截器CommandInterceptor,而执行的execute(command)方法,实际上调用的就是commandInterceptor.execute(commandConfig,command)。而CommandInterceptor中包含了一个set和get方法,用于设置next(实际上就是下一个CommandInterceptor)变量。想象一下,这样就能够通过这种形式找到拦截器链的下一个拦截器链,就可以将命令传递下去。
简单梳理一下:Service实现服务的其中一个标准方法是在具体服务中调用commandExecutor.execute(new command())(这里的command是具体的命令)。其执行步骤就是命令执行器commandExecutor.execute调用了其内部变量CommandInterceptor first(第一个命令拦截器)的execute方法(加上了参数commandConfig)。CommandInterceptor中包含了一个CommandInterceptor对象next,用于指向下一个CommandInterceptor,在拦截器的execute方法中,只需要完成其对应的相关操作,然后执行一下next.execute(commandConfig,command),就可以很简单的讲命令传递给下一个命令拦截器,然后在最后一个拦截器中执行command.execute(),调用这个命令最终要实现的内容就行了。
未完很困,待续。
activiti源码分析(一)设计模式