Activiti之命令拦截器

xiaoxiao2021-02-28  80

Activiti提供了命令拦截器的功能,外界对Activit流程中各个实例进行操作,实际可以被看作是对数据进行相应的操作,在此过程中,Activiti使用了设计模式中的 命令模式, 每一个操作数据库CRUD的操作,均可被看做为一个命令 Command,然后交由命令执行者 CommandExecutor去执行。除此之外,为了能让使用者可以对这些命令进行相应的拦截,Activiti还使用了设计模式中的 职责链模式,使用者可以在其中添加相应的拦截器。

职责模式让多个对象都有机会处理请求,从而避免了请求发送者和请求接收者之间的耦合。这些请求接收者将组成一条链,并沿着这条链传递下去, 直到有一个对象处理这个请求为止,这就形成了一条责任链。

命令设计模式:http://blog.csdn.net/u012867699/article/details/76778699

职责链设计模式:http://blog.csdn.net/u012867699/article/details/76778926

Activiti使用了一个CommandContext类作为命令接收者,该对象维护一系列的Manager对象,这些Manager对象就是J2EE中的DAO对象。 除了命令接收者外,Activiti还使用一系列的CommandInterceptor(命令拦截器),这些命令拦截器扮演命令模式中的命令执行者角色。

Activiti的拦截器,就是结合这两种设计模式,达到拦截器效果的。

所有的命令均需要实现org.activiti.engine.impl.interceptor.Command接口,接口的实现如下:

public interface Command<T> { T execute(CommandContext commandContext); } execute方法的CommandContext参数,该参数为所有的命令提供了获取数据库、事物管理器、扩展属性等资源。由CommandContextInterceptor提供。

Activiti拦截器的运行过程

通过源码分析一下,Activiti拦截器的执行过程

1、设置拦截器

当初始化流程引擎的时候,会执行下面的方法

org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl

public ProcessEngine buildProcessEngine() { init(); ProcessEngineImpl processEngine = new ProcessEngineImpl(this); postProcessEngineInitialisation(); return processEngine; } init()方法源码

public void init() { initConfigurators(); configuratorsBeforeInit(); initHistoryLevel(); initExpressionManager(); if (usingRelationalDatabase) { initDataSource(); } initAgendaFactory(); initHelpers(); initVariableTypes(); initBeans(); initFormEngines(); initFormTypes(); initScriptingEngines(); initClock(); initBusinessCalendarManager(); initCommandContextFactory(); initTransactionContextFactory(); initCommandExecutors(); initServices(); initIdGenerator(); initBehaviorFactory(); initListenerFactory(); initBpmnParser(); initProcessDefinitionCache(); initProcessDefinitionInfoCache(); initKnowledgeBaseCache(); initJobHandlers(); initJobManager(); initAsyncExecutor(); initTransactionFactory(); if (usingRelationalDatabase) { initSqlSessionFactory(); } initSessionFactories(); initDataManagers(); initEntityManagers(); initHistoryManager(); initJpa(); initDeployers(); initDelegateInterceptor(); initEventHandlers(); initFailedJobCommandFactory(); initEventDispatcher(); initProcessValidator(); initDatabaseEventLogging(); initActiviti5CompatibilityHandler(); configuratorsAfterInit(); }

init方法就是进行初始化,其中initCommanExecutors()方法中有initCommandInterceptors方法是对所有拦截器的初始化。

拦截器列表:

1、前置拦截器

这个需要实现CommandInterceptor接口,并配置到流程定义配置文件中。

2、默认的拦截器:

    1. LogInterceptor日志拦截器,拦截器打印执行的日志。

    2.事务拦截器。

    3.CommandContextInterceptor 命令上下文拦截器:

         流程定义;

        注入命令上下文,命令上下文包括数据只有代码;

       调用明上上下文close方法,执行数据保存

3、后置拦截器

     这个需要实现CommandInterceptor接口,并配置到流程定义配置文件中。

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);//调用命令调用者CommandInvoker } }

其中getDefaultCommandInterceptors方法为设置默认拦截器:

//命令上下文拦截器:流程定义,注入命令上下文 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; }

所有的拦截器都会调用CommandInterceptor

public interface CommandInterceptor { <T> T execute(CommandConfig config, Command<T> command); CommandInterceptor getNext(); void setNext(CommandInterceptor next); }

2、构造拦截器链

CommandInterceptor提供next参数的getter和setter方法,next参数为下一个拦截器的对象的引用。N个拦截器通过next属性关联就形成了一个无限的拦截器链。如何调用第一个拦截器Loginterceptor呢? ComandExecutor类用来同一执行所有的命令。在initCommandInterceptors初始化拦截器执行完之后,执行方法initCommandExecutor

public void initCommandExecutor() { if (commandExecutor == null) { CommandInterceptor first = initInterceptorChain(commandInterceptors); commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first); } } 其中initInterceptorChain方法设置拦截器链,并设置第一个拦截器

public CommandInterceptor initInterceptorChain(List<CommandInterceptor> chain) { if (chain == null || chain.isEmpty()) { throw new ActivitiException("invalid command interceptor chain configuration: " + chain); } for (int i = 0; i < chain.size() - 1; i++) { chain.get(i).setNext(chain.get(i + 1)); } return chain.get(0); }

3、org.activiti.engine.impl.TaskServiceImpl类中创建任务

public Task newTask(String taskId) { return commandExecutor.execute(new NewTaskCmd(taskId)); }

CommandExecutor是如何注入的。 在流程引擎初始化的时候 org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl类中initServices方法

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

参考:ACTIVITI源码研究之命令模式执行 http://blog.csdn.net/u012867699/article/details/76778699

拦截器执行顺序

1、前置拦截器如果存在,执行 2、日志拦截器 3、执行事务拦截器 4、执行CommandContext拦截器。这个拦截器执行数据库持久化。在命令中并不执行数据库持久化,持久化在此拦截器中调用context.close();执行。 5、后置拦截器如果存在,执行 6、调用命令拦截器执行

转载请注明原文地址: https://www.6miu.com/read-54819.html

最新回复(0)