每一个操作数据库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、调用命令拦截器执行