对于Digester的使用最近才明白一直以来的疑惑,主要是针对SetNextRule的。以下面的部分的xml为例:
<Server port="8005" shutdown="SHUTDOWN">
<Service name="Catalina">
<Executor name="tomcatThreadPool" maxThreads="150" minSpareThreads="4">
</Executor>
</Service>
</Server>
其对应的Digester的构造代码大致如下:
Digester digester = new Digester();
digester.push(this);
digester.addObjectCreate("Server","org.apache.catalina.core.StandardServer","className");
digester.addSetProperties("Server");
digester.addSetNext("Server","setServer","org.apache.catalina.Server");
digester.addObjectCreate("Server/Service","org.apache.catalina.core.StandardService","className");
digester.addSetProperties("Server/Service");
digester.addSetNext("Server/Service","addService","org.apache.catalina.Service");
digester.addObjectCreate("Server/Service/Executor","org.apache.catalina.core.StandardThreadExecutor","className");
digester.addSetProperties("Server/Service/Executor");
digester.addSetNext("Server/Service/Executor","addExecutor","org.apache.catalina.Executor");
...
按照API文档,当parse时,过程应该是把this(Catalina)对象压栈,看到addObjectCreate就把StandardServer实例压栈,接着第一次看到了addSetNext时会做什么呢?
SetNextRule的api说当碰到下一个pattern元素(此例是'server')时,栈顶对象出栈,并把其作为参数按照method传递给top-1的对象,在此处就是把Server的实例通过Catalina的setServer传递调用,当这个方法完毕,Server也就出栈了。关键就是这句'碰到下一个pattern元素',说的不明不白,网上搜了一堆的资料看也基本上直接翻译的,没有过多的解释。如果不管这句话,暂时直接理解成看到SetNextRule就执行出栈,赋值。那么继续看下面的元素,Service的对象又入栈了,当再次看到addSetNext的时候,此时栈顶的Service出栈,并传给addService作为参数,这个addService的方法是Server的,但是Server出栈了,top-1是Catalina,显然不成立。
那么什么样的流程能解释呢?对应看xml文件,第一次看到Server是<Server>元素的开始,再次看到Server呢,对应的肯定是</Server>结束,这就是所谓的'下一个pattern元素'了,所以此后的过程就非常清晰了。遵循着类似递归的过程,由内而外的执行SetNextRule的匹配规则,Catalina,Server,Service,Executor相继入栈,最先看到下一个pattern元素的是</executor>所以调用Service的addExecutor执行完毕,Executor出栈;接着看到</Service>执行Server的addService,然后Service出栈,随后</Server>执行Catalina的setServer,最后Server出栈。
简单的理解是所谓的'the next pattern element'一般情况下可以看作tag的结束符。这样理解关于Digester的构造简单而且好辨别。虽然没有去看它的源码,但是个人认为这种推理应该是有一定的道理的。