庖丁分词的源码分析(2) 自动更新字典
庖丁分词的字典文件发生改变的时候是会自动更新的,那么这个是怎么实现的呢。其实庖丁做的是比较有意思的,但是第一次看的时候很困惑。用到了递归(不断重复调用自己),和监听器模式。
final DictionariesCompiler compiler = (DictionariesCompiler) compilerClass.newInstance();new Function() {public void run() throws Exception {// 编译词典-对词典进行可能的处理,以符合分词器的要求if (compiler.shouldCompile(p)) {Dictionaries dictionaries = readUnCompiledDictionaries(p);Paoding tempPaoding = createPaodingWithKnives(p);setDictionaries(tempPaoding, dictionaries);compiler.compile(dictionaries, tempPaoding, p);}// 使用编译后的词典final Dictionaries dictionaries = compiler.readCompliedDictionaries(p);setDictionaries(finalPaoding, dictionaries);// 启动字典动态转载/卸载检测器// 侦测时间间隔(秒)。默认为60秒。如果设置为0或负数则表示不需要进行检测String intervalStr = getProperty(p,Constants.DIC_DETECTOR_INTERVAL);int interval = Integer.parseInt(intervalStr);if (interval > 0) {dictionaries.startDetecting(interval,new DifferenceListener() {public void on(Difference diff)throws Exception {dictionaries.stopDetecting();// 此处调用run方法,以当检测到**编译后**的词典变更/删除/增加时,// 重新编译源词典、重新创建并启动dictionaries自检测run();}});}}}.run();首先我们看到一个function,他有个run方法,里面有个监听器,当条件成立,这个监听器会执行这个run方法。run方法的作用是设置字典对象。
我们在run方法里改变的是finalPaoding,但是finalPaoding=Paoding。所以我们改变的就是自身。
当然这里的run方法不是直接去和监听器打交道,中间有个Detector,run方法把Listener和检查的时间间隔都设置到Detector里去,剩下的事情就有Detector来完成了。
Detector会怎么做呢。他会执行自己的start方法:
public void start(boolean daemon) {if (lastSnapshot == null) {lastSnapshot = flash();}thread = new Thread(this);thread.setDaemon(daemon);thread.start();}这个start方法会新创建个自己的线程,再来看看Detector的run方法:他会
listener.on(diff);,就是触发监听器。这个监听器的on方法在最原始的run方法中已经定义了,其实就是调用run方法自己。这样新的一轮就开始,然后每到监听的时间间隔就会重新开始一轮,这样不断下去。