Activiti之命令拦截器
来源:互联网 发布:软件企业两免三减半 编辑:程序博客网 时间:2024/06/04 01:29
每一个操作数据库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、调用命令拦截器执行
- Activiti之命令拦截器
- Activiti入门教程四(自定义Activiti命令拦截器)
- 【工作流前进之路】Activiti 研究之拦截器
- activiti入门五(自定义拦截器)
- ACTIVITI 源码研究之命令模式执行
- ACTIVITI 源码研究之命令模式执行
- ACTIVITI 源码研究之命令模式执行
- AxonFramework命令拦截器
- Activiti核心架构之职责链与命令模式
- struts2之拦截器
- struts2 之 拦截器
- Struts2之拦截器
- Struts2之拦截器
- Struts之拦截器
- struts2之拦截器
- EJB之拦截器
- springMVC之拦截器
- struts之拦截器
- SLAM数据集
- 使用Windows API保存配置参数
- 【结构体排序】HDU4883TIANKENG’s restaurant【BestCoder Round #2】
- DB2移动数据实用工具的使用
- 第十二届北京师范大学程序设计竞赛决赛训练总结【7/10】
- Activiti之命令拦截器
- linux用户和组相关文件
- Day43-Struts01
- 【2017.8.6普及模拟】最大(max)
- POJ 3260 The Fewest Coins(动态规划+多重背包+完全背包)
- Java类的定义与实例化
- idea环境基于maven整合ssm
- 帅帅哥曾经遇到面试相关
- mongoDB 详解 三、mongoDB 的增删改