程序员

Activiti之CommondExecutor

2017-06-15  本文已影响1064人  yingzong

Activiti提供了一组Service,向用户暴露流程引擎的功能,Service内部通过命令模式执行真正的操作。以RepositoryService的流程部署方法deploy为例:

public class RepositoryServiceImpl extends ServiceImpl implements RepositoryService {
...
    public Deployment deploy(DeploymentBuilderImpl deploymentBuilder) {
        return commandExecutor.execute(new DeployCmd<Deployment>(deploymentBuilder));
    }
...
}

从代码中可以看到deploy方法执行的是DeployCmd,执行命令的是一个叫commandExecutor的对象,这个对象从哪里来?有什么功能?

CommandExecutor的初始化

Activiti在初始化流程引擎ProcessEngine时,初始化了CommandExecutor对象:

public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfiguration {
    ...
    //初始化方法
    protected void init() {
        ...
        initCommandExecutors();
        ...
    }
    
    //初始化CommandExecutor
    protected void initCommandExecutors() {
        ...
        initCommandInvoker();
        initCommandInterceptors();
        initCommandExecutor();
    }
    ...
}

从初始化代码中可以看到,CommandExecutor的初始化分为3部分:Invoker Interceptor Executor

`Invoker`和`Interceptor`的继承结构

从上图中可以看到,CommondInvokerCommandInterceptor的子类,CommandInvoker不能指定next值,execute方法中执行了真正的命令。

public class CommandInvoker extends AbstractCommandInterceptor {

    @Override
    public <T> T execute(CommandConfig config, Command<T> command) {
        return command.execute(Context.getCommandContext());
    }
    ...
    @Override
    public void setNext(CommandInterceptor next) {
        throw new UnsupportedOperationException("CommandInvoker must be the last interceptor in the chain");
    }
}

initCommandExecutor方法中,会将CommandInteceptorCommandInvoker构造成调用链,并用CommandExecutor的first指针指向调用链的第一个CommandInterceptor

command调用链.png

CommandExecutor的执行

commandExecutor.execute(new DeployCmd<Deployment>(deploymentBuilder));

当调用CommandExecutorexecute方法时,会调用first的execute方法,执行CommandInterceptor调用链:

public <T> T execute(CommandConfig config, Command<T> command) {
    return first.execute(config, command);
}

以Activiti实现的LogInterceptor为例,execute方法中执行了打日志的代码后,会继续执行下一个CommandInterceptor

log.debug(...)
return next.execute(config, command);

最终在CommandInvoker中会执行Command

public <T> T execute(CommandConfig config, Command<T> command) {
    return command.execute(Context.getCommandContext());
}

CommandExecutor扩展

在Activiti中,可以实现自己的CommandInterceptor,在初始化ProcessEngine时加载到调用链中。例如Activiti在结合Spring时,就是通过实现自定义的事务CommandInterceptor,在拦截器中开启事务,调用next方法。

上一篇下一篇

猜你喜欢

热点阅读