flowable中的責任鏈模式
如下,以RuntimeServiceImpl爲例, 在flowable源碼中很多這樣的調用,這就是典型的責任鏈模式的應用。
此處關鍵在於實現了ServiceImpl這個類,如下所示,flowable的幾大主要類都實現了該接口。
相關的類結構圖如下:
public CommandInterceptor initInterceptorChain(List<CommandInterceptor> chain) {
if (chain == null || chain.isEmpty()) {
throw new FlowableException("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);
}
可以看到責任鏈的前後關係是按照列表中的順序的,所以關鍵點在於傳參,找到調用這個方法的地方:
public void initCommandExecutor() {
if (commandExecutor == null) {
CommandInterceptor first = initInterceptorChain(commandInterceptors);
commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first);
}
}
參數commandInterceptors是ProcessEngineConfigurationImpl類的一個成員變量,所以接下來要看看哪裏初始化這個成員變量,如下:
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);
}
}
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;
}
接着runtimeService也會進行相關初始化,其中責任鏈結構如下:
查看前四個節點,如下以LogInterceptor爲例,肯定會有next.execute(config, command);
, 這也是保證責任鏈能夠往下走的決定因素。
接下來再看看最後一個節點CommandInvoker的源碼,關鍵是執行了command的execute方法,沒有next.execute了。
同時可以發現getNext()返回爲null, 即獲取不到下一個節點,並且在嘗試設置下一個節點時會拋出異常,這也正是責任鏈鏈尾節點應有的特徵。
由此也可以看出所有業務邏輯的處理最終會通過comand.execute來完成,所以接下來就是要搞清楚Command的處理邏輯,具體請待下一篇分析。