在公司一个常规模块中,准备使用责任链的模式处理业务,但是不想使用Apache Camel这样很大的框架,于是乎想到了Commons-Chain这个很小很轻便的框架,所以准备花点时间研究下Commons-Chain的框架代码。
Commons-Chain有5个很重要接口:Catalog,Chain,Command,Context,Filter
Catalog:储存Command的地方,其目的是我们不需要知道Command的classname,只需要关注我们赋予 Command对应的name
Chain:继承了Command接口,一条chain当中可以有很多Command,而且Chain也是一条Command, 所以Chain可以嵌入到另外一条Chain里面使用
Command:最顶级的基本接口,定义了execute(Context context)方法,同时提供了 CONTINUE_PROCESSING和PROCESSING_COMPLETE的两个静态boolean变量
Context:上下文接口,集成于Map
Filter:是一个特殊的Command,一个Command在执行的时候,如果它是实现了Filter接口的,就会调用 postprocess(Context context, Exception exception)这个方法
我们先解析这条接口结构,Command->Chain->ChainBase,上下文我们则采用Context->ContextBase
package com.axxis.service.atgneo;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.impl.ChainBase;
import com.lanecrawford.webservice.productcatalog.bean.PRODUCT;
public class ProductCommandChain extends ChainBase {
public ProductCommandChain() {
addCommand(new LoadBasicData());
addCommand(new BuildProductFromUda());
}
public static void main(String[] args) throws Exception {
Command prosser = new ProductCommandChain();
ProductConext context = new ProductConext();
prosser.execute(context);
for (PRODUCT pro : context.getPRODUCTS()) {
System.out.println(pro);
}
}
}
这就是一个最基本的责任链的使用,一是往Chain里面addCommand,二是将这个Chain本身作为一个上层的Command调用execute方法,并传入我们的context上下文
首先我们看看ChainBase这个类,
4个构造器,一目了然;commands存放我们command的地方,frozen是一个开关,默认为false(关闭),当Command执行execute的时候,frozen被置为true,这个时候ChainBase中的addCommand无法正常执行,会抛出异常
protected boolean frozen = false;
public void addCommand(Command command) {
if (command == null) {
throw new IllegalArgumentException();
}
if (frozen) {
throw new IllegalStateException();
}
Command[] results = new Command[commands.length + 1];
System.arraycopy(commands, 0, results, 0, commands.length);
results[commands.length] = command;
commands = results;
}
最后需要关注的是下面这段代码
boolean handled = false;
boolean result = false;
for (int j = i; j >= 0; j--) {
if (commands[j] instanceof Filter) {
try {
result =
((Filter) commands[j]).postprocess(context,
saveException);
if (result) {
handled = true;
}
} catch (Exception e) {
// Silently ignore
}
}
}
就是我们Command在exceute的时候按照Commad[]逆序调用postprocess方法(如果这个Command实现了Filter这个接口)。
ok明天接着写