Activiti核心架構之職責鏈與命令模式
Activiti核心的骨架是:命令模式+職責鏈
本文的程式碼版本:activiti 5.22
一、職責鏈
1、什麼是職責鏈模式
http://blog.csdn.net/jiankunking/article/details/50443294
2、Activiti中職責鏈初始化
流程初始化流程引擎的時候會初始化很多資訊,具體如下:
protected void init() {
initConfigurators();
configuratorsBeforeInit();
initProcessDiagramGenerator();
initHistoryLevel();
initExpressionManager();
initDataSource();
initVariableTypes();
initBeans();
initFormEngines();
initFormTypes();
initScriptingEngines();
initClock();
initBusinessCalendarManager();
initCommandContextFactory();
initTransactionContextFactory();
initCommandExecutors();
initServices();
initIdGenerator();
initDeployers();
initJobHandlers();
initJobExecutor();
initAsyncExecutor();
initTransactionFactory();
initSqlSessionFactory();
initSessionFactories();
initJpa();
initDelegateInterceptor();
initEventHandlers();
initFailedJobCommandFactory();
initEventDispatcher();
initProcessValidator();
initDatabaseEventLogging();
configuratorsAfterInit();
}
由於本文主要探究:職責鏈與命令模式,所以這裡只需要關注initCommandExecutors()即可,在該方法中會進行如下初始化:
protected void initCommandExecutors() {
//初始化命令上下文
initDefaultCommandConfig();
initSchemaCommandConfig();
//初始化CommandInvoker
initCommandInvoker();
//初始化命令攔截器
//預設會新增LogInterceptor、TransactionInterceptor、CommandContextInterceptor、CommandInterceptor攔截器
initCommandInterceptors();
//初始化命令執行器
//先初始化攔截器之間的指向關係,並獲取到職責鏈的第一個元素first
//根據CommandConfig與first來初始化CommandExecutorImpl類的例項
initCommandExecutor();
}
後面三個方法具體程式碼如下:
protected List<CommandInterceptor> customPreCommandInterceptors;
protected List<CommandInterceptor> customPostCommandInterceptors;
protected void initCommandInvoker() {
if (commandInvoker==null) {
commandInvoker = new CommandInvoker();
}
}
protected 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);
}
}
protected void initCommandExecutor() {
if (commandExecutor==null) {
CommandInterceptor first = initInterceptorChain(commandInterceptors);
commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first);
}
}
方法之間的呼叫關係及初始化了哪些資訊如下圖所示:
最終命令攔截器鏈就是:
customPreCommandInterceptors->LogInterceptor->TransactionInterceptor->CommandContextInterceptor->customPostCommandInterceptors->commandInvoker
注意:commandInvoker是CommandInterceptor的例項,即最後攔截的是具體命令的執行。
在初始化過程中主要用到幾個介面結構如下:
3、自定義Activiti命令攔截器
通過上面兩部分大家應該清楚了,activiti職責鏈:是在哪?如何初始化?這個兩個問題了。
那麼我們應該如何自定義一個攔截器,並指定其在職責鏈中的位置呢?
其實,很簡單:
1、自定義攔截器
public class InterceptorTest extends AbstractCommandInterceptor {
@Override
public <T> T execute(CommandConfig config, Command<T> command) {
//輸出字串和命令
System.out.println("this is InterceptorTest----->" + command.getClass().getName());
//然後讓職責鏈中的下一個請求處理者處理命令
return next.execute(config, command);
}
}
2、繼承ProcessEngineConfigurationImpl根據需要重寫其中的方法
public class MyProcessEngineConfiguration extends ProcessEngineConfigurationImpl {
@Override
protected CommandInterceptor createTransactionInterceptor() {
// 事務攔截器 在activiti預設初始化的時候是空的
// 此處返回自定義攔截器InterceptorTest2
return new InterceptorTest2();
}
@Override
protected Collection<? extends CommandInterceptor> getDefaultCommandInterceptors() {
//通過重寫父類ProcessEngineConfigurationImpl中的getDefaultCommandInterceptors方法
//可以自定義攔截器的位置
//以及新增哪一些攔截器
List<CommandInterceptor> interceptors = new ArrayList<>();
interceptors.add(new LogInterceptor());
CommandInterceptor transactionInterceptor = createTransactionInterceptor();
if(transactionInterceptor!=null) {
interceptors.add(transactionInterceptor);
}
interceptors.add(new InterceptorTest());
interceptors.add(new CommandContextInterceptor(commandContextFactory,this));
return interceptors;
}
}
3、在配置檔案中注入
<bean id="processEngineConfiguration" class="com.bpm.example.test.MyProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:mysql://10.10.10.10:3306/activiti-test?useUnicode=true&characterEncoding=utf8" />
<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="root" />
<property name="databaseSchemaUpdate" value="true" />
<property name="asyncExecutorActivate" value="false" />
<!--<property name="mailServerHost" value="mail.my-corp.com" />-->
<!--<property name="mailServerPort" value="5025" />-->
</bean>
二、命令模式
1、什麼是命令模式
http://blog.csdn.net/jiankunking/article/details/50767837
2、Activiti中命令模式的使用
1、Command(定義命令的介面,宣告執行的方法)
與標準的Command模式不同之處,就是execute方法中增加了CommandContext資訊,這個類可以說是執行命令的上下文
public interface Command <T> {
T execute(CommandContext commandContext);
}
2、CommandExecutor(命令執行器,用於執行命令)
其中CommandConfig是命令的配置
/**
* The command executor for internal usage.
*
* @author Tom Baeyens
*/
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);
}
3、ServiceImpl類
所有的服務類繼承這個,其實就一個作用,持有CommandExecutor類,這個類是命令的傳送者(類似於命令模式一文中的:電視遙控器)。
public class ServiceImpl {
protected ProcessEngineConfigurationImpl processEngineConfiguration;
public ServiceImpl() {
}
public ServiceImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
this.processEngineConfiguration = processEngineConfiguration;
}
protected CommandExecutor commandExecutor;
public CommandExecutor getCommandExecutor() {
return commandExecutor;
}
public void setCommandExecutor(CommandExecutor commandExecutor) {
this.commandExecutor = commandExecutor;
}
}
簡單梳理一下:
Service實現服務的其中一個標準方法是在具體服務中呼叫commandExecutor.execute(new command())(這裡的command是具體的命令)。其執行步驟就是命令執行器commandExecutor.execute呼叫了其內部變數CommandInterceptor first(第一個命令攔截器)的execute方法(加上了引數commandConfig)。
CommandInterceptor類中包含了一個CommandInterceptor物件next,用於指向下一個CommandInterceptor,在攔截器的execute方法中,只需要完成其對應的相關操作,然後執行一下next.execute(commandConfig,command),就可以很簡單的將命令傳遞給下一個命令攔截器,然後在最後一個攔截器中執行command.execute(),呼叫這個命令最終要實現的內容就行了。
本文參考:http://www.cnblogs.com/lighten/p/5863102.html
本文demo:https://github.com/jiankunking/bpm_demo
作者:jiankunking 出處:http://blog.csdn.net/jiankunking
相關文章
- 設計模式之-職責鏈模式設計模式
- 設計模式之【職責鏈模式】設計模式
- 職責鏈模式模式
- Javascript設計模式之職責鏈模式JavaScript設計模式
- javascript設計模式 之 10 職責鏈模式JavaScript設計模式
- C#設計模式之職責鏈模式C#設計模式
- 實話設計模式之:職責鏈設計模式
- 設計模式-職責鏈模式設計模式
- 職責鏈模式(chain of responsibility)模式AI
- 行為性職責鏈模式模式
- 實驗15:職責鏈模式模式
- 前端架構的職責前端架構
- JAVA設計模式之 職責鏈模式【Chain of Responsibility Pattern】Java設計模式AI
- 設計模式系列 12– 職責鏈模式設計模式
- 簡說設計模式——職責鏈模式設計模式
- JS設計模式五:職責鏈模式JS設計模式
- Python設計模式-職責鏈模式Python設計模式
- 使用職責鏈模式來重構你的程式碼模式
- Dubbo架構設計與原始碼解析(三)責任鏈模式架構原始碼模式
- 設計模式-職責鏈模式(Chain of Responsibility)設計模式AI
- 《JavaScript設計模式與開發實踐》模式篇(10)—— 職責鏈模式JavaScript設計模式
- PHP實現職責鏈設計模式PHP設計模式
- 設計模式(十六)職責鏈模式(Chain of Responsibility)設計模式AI
- 請求的鏈式處理——職責鏈模式(四)模式
- 請求的鏈式處理——職責鏈模式(三)模式
- 請求的鏈式處理——職責鏈模式(二)模式
- 請求的鏈式處理——職責鏈模式(一)模式
- 軟體設計模式學習(十七)職責鏈模式設計模式
- (轉)職責鏈設計模式(Chain of Responsibility)設計模式AI
- 職責鏈模式的一篇文章模式
- 設計模式之——責任鏈模式設計模式
- 設計模式之責任鏈模式設計模式
- 軟體架構師的工作職責架構
- Java進階篇設計模式之八 ----- 責任鏈模式和命令模式Java設計模式
- C++設計模式——職責鏈模式( Chain of Responsibility Pattern)C++設計模式AI
- C#設計模式系列:職責鏈模式(Chain of Responsibility)C#設計模式AI
- c/c++ 設計模式-----職責鏈(Chain Of Responsibility)模式C++設計模式AI
- PHP 設計模式之責任鏈模式PHP設計模式