把自己的一些粗糙想法写出来,即是对自己的一个总结,也能对其他人有些帮助。简单随笔,若在实现中遇到问题,具体再聊。
Eclipse中的插件都是XML文件来进行描述,比如:
这段XML描述了插件的绝大多数信息,包括插件的ID,name,版本,启动类,同时所有的扩展节点也都在这里定义,该插件对外提供的库以及资源也都要定义在这个文件中。
文件的名称为“plugin.xml”Eclipse启动的时候会扫描“plugins”目录下的所有 “plugin.xml”文件,进而装载所有的插件,因此,需要用XML Parser 将这些信息Parser出来,形成插件的基本信息,具体选用DOM、SAX、还是Pull Parser 都无所谓。
Eclipse采用微内核+插件的模式构架,也就是说,除了一个微小的核儿之外,所有的东西都是插件(All are plugins)。
Eclipse Plugin Framework 最核心的概念就要算“Extension Point(扩展点)”了。打个比方,“Extension Point”就像我们日常生活中的插销板,而Extension 就是能够插入到这个插销板上面的插销。
系统的开放性很大程度上取决于系统究竟给你多少Extension Point。
对于Eclipse来说,因为采用微内核+插件的方式,因此,定义扩展点是很重要的步骤,在扩展功能的同时,你可以在任何你觉得可能被扩展的地方定义扩展点,来方便其他人扩展系统的功能。
举个例子,Eclipse UI中,工具栏、视图都留有扩展点,这样可以方便的进行扩展。
Eclipse的插件扩展点都定义在plugin.xml,每个插件要扩展那些扩展点也定义在这个文件中。你可以搜索eclipse的安装目录,会发现数以百计的plugin.xml文件
了解Eclipse的Plugin Framework 需要对ClassLoader(类装载器)有比较深的理解。
ClassLoader——顾名思义,就是Java中用来装载类的部分,要将一个类的名字装载为JVM中实际的二进制类数据。在JVM中,任何一个类被加载,都是通过ClassLoader来实现的,同时,每个Class对象都有一个引用指向装载他的ClassLoader,你可以通过getClassLoader()方法得到它。
ClassLoader是一个抽象类,你可以定义自己的ClassLoader来实现特定的Load功能。Eclipse Plugin Framework就实现了自己的ClassLoader。
ClassLoader使用的是“Delegation Model(双亲委托模型)”来查找,定位类资源。每一个ClassLoader都有一个父ClassLoader实例(在构造的时候传入),当这个ClassLoader被要求加载一个类时,他首先会询问自己的父ClassLoader,看看他能否加载,如果不能,则自己加载。
最后来看一下代码:
可见,ClassLoader首先会查找该类是否已经被装载,如果没有,就询问自己的父ClassLoader,如果还不能装载,就调用findClass()方法来装载类。所以,一般简单的自定义ClassLoader只需要重写findClass方法就可以了。
简单demo准备,实现过程。
我们模拟几个重要的类是:
Plugin:插件类,描述每个具体的插件。
PluginDesciptor: 插件描述符,记录了插件的ID,Name,Version,依赖,扩展点等。
PluginManager:插件管理器,负责所有插件资源的管理,包括插件的启动,停止等。
PluginRegistry:插件注册表,提供了一个由插件ID到plugin的映射。
package com.bjrongzhi.nms.client.plugins.core;
import org.java.plugin.Plugin;
public class PluginCore extends Plugin {
protected void doStart() throws Exception { }
protected void doStop() throws Exception { }
}
|
<?xml version="1.0" ?> <!DOCTYPE plugin PUBLIC "-//JPF//Java Plug-in Manifest 1.0" "http://jpf.sourceforge.net/plugin_1_0.dtd"> <plugin id="com.bjrongzhi.nms.client.plugins.core" version="1.0.0" > <runtime> <library id="core" path="/" type="code"> <export prefix="*" /> </library> </runtime>
<!-- 定义两个扩展点PopupMenu和MainMenu--> <extension-point id="PopupMenu"> <parameter-def id="class"/> <parameter-def id="name"/> </extension-point> <extension-point id="MainMenu"> <parameter-def id="class"/> <parameter-def id="name"/> </extension-point> </plugin> |
package com.bjrongzhi.nms.client.plugins.popupmenu;
/** * 仿真管理系统右键菜单 * * @author zhangdy * */ public class ResMgrPopupMenu extends AbstractPopupMenu { //省略…….. JMenuItem mi_deleteSubnet = new JMenuItem("删除子网"); JMenuItem mi_createLable = new JMenuItem("创建标签"); public ResMgrPopupMenu() {
mi_createPerfSnmp.addActionListener(new DoCreatePerfSnmp());/ /省略……..
// 站点界面的右键菜单 table_menu.put(ClientMainPane.class.getName(), new JMenuItem[] { mi_createSdhNe, // mi_createShelf, // mi_createIPNe, mi_createPerfmonitortask, mi_createPerfSnmp, // mi_createPerfTest // // 测试 });
} |
<?xml version="1.0" ?> <!DOCTYPE plugin PUBLIC "-//JPF//Java Plug-in Manifest 1.0" "http://jpf.sourceforge.net/plugin_1_0.dtd"> <plugin id="com.bjrongzhi.nms.client.plugins.popupmenu" version="1.0.0"> <!-- 该插件依赖的插件在这里定义 --> <requires> <import plugin-id="com.bjrongzhi.nms.client.plugins.core"/> </requires> <runtime>
<!-- PluginClassLoader会将根目录都加入到URLClassLoader的类搜索路径中去, 这样,就可以用这个类加载器来加载相应的插件类和资源了。--> <library id="popupmenu" path="/" type="code"> <export prefix="*" /> </library> </runtime>
<!-- 这是core关于PopupMenu的扩展点,这是"ResMgrPopupMenu"插件中对此扩展点的一个扩展声明,声明了自己扩展的类和名称。Name 只是定义该扩展点的名称,而其中的"class"则是为了加载真正的功能。 --> <extension plugin-id="com.bjrongzhi.nms.client.plugins.core" point-id="PopupMenu" id="resmgrpopupmenu"> <parameter id="class" value="com.bjrongzhi.nms.client.plugins.popupmenu.ResMgrPopupMenu"/> <parameter id="name" value="ResMgrPopupMenu"/> </extension> </plugin> |
package com.bjrongzhi.nms.client.topo.menu;
import com.bjrongzhi.nms.client.topo.ClientMainPane;
public class PluginTools {
public static PluginTools instance = new PluginTools(); public static PluginManager pluginManager; public static PluginDescriptor core; // TODO private TNetwork network = ClientMainPane.network;
static { try { ExtendedProperties config = new ExtendedProperties(System .getProperties()); PluginsCollector collector = new DefaultPluginsCollector(); collector.configure(config);
pluginManager = ObjectFactory.newInstance(config).createManager(); Collection<PluginLocation> pluginLocations = collector .collectPluginLocations();
pluginManager.publishPlugins((PluginLocation[]) pluginLocations .toArray(new PluginLocation[pluginLocations.size()])); // Create instance of plug-in manager.
/* * 得到插件描述符,描述符中记录了插件的ID,Name,Version,依赖,扩展点等。 * 通过Plugin.xml文件得知,关于core的扩展点有两个:PopupMenu和MainMenu。这两个扩展点都声 * 明了自己扩展的类和名称.Name 只是定义该扩展点的名称,Class则为了加载真正的功能。 */ core = pluginManager.getRegistry().getPluginDescriptor( "com.bjrongzhi.nms.client.plugins.core"); } catch (JpfException e) { text-align: justify; margin: 0cm
0
顶
0
踩 发表评论 |
评论