Activiti源码分析(框架、核心类。。。)

LD is tigger forever,CG are not brothers forever, throw the pot and shine forever.
Modesty is not false, solid is not naive, treacherous but not deceitful, stay with good people, and stay away from poor people.
talk is cheap, show others the code,Keep progress,make a better result.
Survive during the day and develop at night。

目录

概 述

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));
  }
 
  ...
}

其实activiti中大部分操作都是基于设计模式中的命令模式完成的(这里还使用了职责链模式,构造了命令拦截器链,用于在命令真正被执行之前做一系列操作)。下面结合源码详细介绍一下这些设计思路:

命令模式的本质在于将命令进行封装,发出命令和执行命令分离。职责链模式只需要将请求放入职责链上,其处理细节和传递都不需要考虑。activiti将这两个模式整合在一起,构成了其服务主要的实现方式。其核心只有三个部分:CommandExecutor(命令执行器,用于执行命令),CommandInterceptor(命令拦截器,用于构建拦截器链),Command(命令自身)。

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(),调用这个命令最终要实现的内容就行了。
实现一个自定义的命令只需要实现Command接口,在execute中做相应的操作就行了,而实现一个自定义的命令拦截器需要继承AbstractCommandInterceptor,在execute中做相应的处理,最后调用next.execute()即可,而命令执行器虽然也可以自己实现,但是没有多大意义,非常麻烦。
命令执行器会先执行命令拦截器链的execute方法,但命令拦截器链是如何构建的,命令又是在哪里调用的,第一个拦截器是如何添加到命令执行器的,这些都要关注于Activiti工作流引擎的初始化。
初始化的方法主要写在了org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl类的init()方法中,这里主要关注于其中的initCommandExecutors(),如果对activiti的配置不清楚的,可以好好的了解一下这个初始化过程。
  initCommandExecutors():

protected void initCommandExecutors() {
   initDefaultCommandConfig();
   initSchemaCommandConfig();
   initCommandInvoker();
   initCommandInterceptors();
   initCommandExecutor();
 }
在这里插入代码片

这五个方法名很清楚地说明了初始化步骤,前两步都是初始化CommandConfig,第一个就是命令执行器的defaultConfig,主要用在transaction拦截器。
第三步初始化命令执行者,这也是一个拦截器,不过其放在拦截器的尾端,最后一个执行,它的execute方法就是调用了command.execute()。第四步就是初始化命令拦截器了。最后一步初始化命令执行器。

/**
*  CommandConfig实际就这两个配置
*/
public class CommandConfig {
 
  private boolean contextReusePossible;
  private TransactionPropagation propagation;
   
  // DefaultConfig
  public CommandConfig() {
    this.contextReusePossible = true;
    this.propagation = TransactionPropagation.REQUIRED;
  }
 
  // SchemaCommandConfig
  public CommandConfig transactionNotSupported() {
    CommandConfig config = new CommandConfig();
    config.contextReusePossible = false;
    config.propagation = TransactionPropagation.NOT_SUPPORTED;
    return config;
  }
}
public class CommandInvoker extends AbstractCommandInterceptor {
 
  @Override
  public <T> T execute(CommandConfig config, Command<T> command) {
    return command.execute(Context.getCommandContext());
  }
 
  @Override
  public CommandInterceptor getNext() {
    return null;
  }
 
  @Override
  public void setNext(CommandInterceptor next) {
    throw new UnsupportedOperationException("CommandInvoker must be the last interceptor in the chain");
  }
 
}

最后我们看一看默认提供的三个拦截器都做了一些什么操作(不包括最后CommandInvoker,上面已给出)。
LogInterceptor.execute():
TransactionInterceptor.execute()(这是一个抽象的方法,需要自己实现,下面以与spring集成后所给的实现为例)
 SpringTransactionInterceptor:
 这里值得注意的是context.close()方法,这里将调用session.flush();,真正执行完成数据库操作。Context也是一个比较重要的类,有兴趣可以研究一下。

总结:

相关工具如下:

分析:

小结:

主要讲述了接下来Activiti源码分析,请大家指正~

参考资料和推荐阅读

1.链接: 参考资料.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

执于代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值