?? 當(dāng)某個(gè)插件需要被加載時(shí),
Nutch
會加載所有插件的相關(guān)接口到緩存,此后每個(gè)插件需要實(shí)例的時(shí)候,根據(jù)相關(guān)接口和相關(guān)接口實(shí)現(xiàn)實(shí)例在緩存內(nèi)的記錄,使用反射實(shí)現(xiàn)一個(gè)實(shí)例并返回,下面以
QueryFilter
的所有插件被加載例子進(jìn)行說明。
?
具體代碼參看org.apache.nutch.seacher.QueryFilters<init>
(
1
)當(dāng)?shù)谝淮涡枰玫?/span>
QueryFilter
的一個(gè)子類的實(shí)例時(shí),使用下面這句話試圖獲得所有的實(shí)例:
?
this.queryFilters =
(QueryFilter[]) conf.getObject(QueryFilter.class .getName());
?
(2)如果為空,則試圖從插件倉庫中得到該插件的擴(kuò)展點(diǎn):
?
ExtensionPoint point = PluginRepository.get(conf)
??????????? .getExtensionPoint(QueryFilter.X_POINT_ID);
?
在
PluginRepository.get(conf)
這句話中,返回插件倉庫,如果倉庫為空,會初始化所有插件:
?
初始化所有插件PluginRepository.<init>
|
①????
試圖從緩存內(nèi)獲得插件倉庫。
PluginRepository result = (PluginRepository)CACHE.get(conf);
②????
如果未獲得,則初始化所有插件
result = new PluginRepository(conf);
l????????
初始化以活動插件和擴(kuò)展點(diǎn)的集合
fActivatedPlugins = new HashMap();
????? fExtensionPoints = new HashMap();
????? this.conf = conf;
l????????
獲得插件存放位置
????
?String[] pluginFolders = conf.getStrings("plugin.folders");
l????????
實(shí)例化PluginManifestParser:
?
?PluginManifestParser manifestParser =? new PluginManifestParser(conf, this);
?? PluginManifestParser
是一個(gè)封裝了PluginRepository的工具類,在構(gòu)造時(shí),分析每個(gè)插件的文件夾,把每個(gè)plugin.xml文件的內(nèi)容進(jìn)行分析,記錄了所有的插件接口和插件接口內(nèi)所包含的所有實(shí)現(xiàn)類的關(guān)系。
l????????
放入緩存
??
CACHE.put(conf, result);
?
Plugin.xml
描述內(nèi)容見附錄一
|
?
(3)獲得所有QueryFilter的子類描述。
Extension[] extensions = point.getExtensions();
?
(4)循環(huán)獲得每個(gè)插件的兩個(gè)參數(shù),fieldName和rawFieldNames,生成每個(gè)filter插件實(shí)例。
for (int i = 0; i < extensions.length; i++) {
????????? Extension extension = extensions[i];
????????? ArrayList fieldNames = parseFieldNames(extension, "fields");
????????? ArrayList rawFieldNames = parseFieldNames(extension, "raw-fields");
????????? if (fieldNames.size() == 0 && rawFieldNames.size() == 0) {
??????????? if (LOG.isWarnEnabled()) {
????????????? LOG.warn("QueryFilter: " + extension.getId()
???????????????????? + " names no fields.");
??????????? }
??????????? continue;
????????? }
????????? filters[i] = (QueryFilter) extension.getExtensionInstance();
????????? FIELD_NAMES.addAll(fieldNames);
????????? FIELD_NAMES.addAll(rawFieldNames);
????????? conf.setObject("FIELD_NAMES", FIELD_NAMES);
????????? RAW_FIELD_NAMES.addAll(rawFieldNames);
????????? conf.setObject("RAW_FIELD_NAMES", RAW_FIELD_NAMES);
???
????}
?
至此,所有實(shí)現(xiàn)QueryFilter的子類實(shí)例均被加載。如果需要開發(fā)自己的插件,同樣可以參考這個(gè)過程,plugin.xml的具體內(nèi)容的描述負(fù)在下面:
?
<?xml version="1.0" encoding="UTF-8"?>
?
<!—
插件的根元素,根元素的屬性表明了一個(gè)插件的基本身份-->
<plugin id=”
唯一身份(被插件倉庫作為身份標(biāo)示)” name=”名稱” version=”版本號”
provider=”
作者”class=”類名(可選)”>
?
<!--
以下兩個(gè)內(nèi)容中引用的類庫,都是作為本類使用反射時(shí)生成實(shí)例所需要的類庫-->
<runtime>
??? <library name="
運(yùn)行時(shí)的類庫">
???????
?<!—
如果存在此元素,則保存到fExportedLibs(輸出類庫集合),否則存放到
fNotExportedLibs
(非輸出類庫集合)-->
???????? <export name="*"/>
??? </library>
</runtime>
?
<requires>
??? <!—
需要注意,此處所需要的類庫,包括該類庫所需的類庫,都不得在此引用本插件-->
??? <import plugin="
所需類庫"/>
</requires>
?
<extension id="
本類的包名(從代碼中看沒有被使用)"
????????????? name="
類名(從代碼中看沒有被使用)"
????????????? point="
擴(kuò)展點(diǎn)類名(即接口名)">
????? <implementation id="
實(shí)現(xiàn)擴(kuò)展的唯一標(biāo)識(與類名相同,被parse-plugins.xml
作為身份表示使用)"
?????????? class="
實(shí)現(xiàn)擴(kuò)展的類的類名"/>
????? <parameter name="
參數(shù)名"? value="參數(shù)值"/>
</extension>
?
<!—
僅在nutch-extensionpoints\plugin.xml中存在,一次性加載紀(jì)錄下所有的擴(kuò)展點(diǎn)的名稱-->
<
extension-point id=”
擴(kuò)展點(diǎn)唯一標(biāo)識”name=”擴(kuò)展點(diǎn)名”/>
?
</plugin>
下次會寫一個(gè)完整的plugin以供參考。
轉(zhuǎn)載請注明出處。