第一个自定义插件的实现

自定义插件的实现

把自己的一些粗糙想法写出来,即是对自己的一个总结,也能对其他人有些帮助。简单随笔,若在实现中遇到问题,具体再聊。

插件清单

Eclipse中的插件都是XML文件来进行描述,比如:

这段XML描述了插件的绝大多数信息,包括插件的IDname,版本,启动类,同时所有的扩展节点也都在这里定义,该插件对外提供的库以及资源也都要定义在这个文件中。

 

文件的名称为“plugin.xmlEclipse启动的时候会扫描“plugins”目录下的所有 plugin.xml”文件,进而装载所有的插件,因此,需要用XML Parser 将这些信息Parser出来,形成插件的基本信息,具体选用DOMSAX、还是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文件

ClassLoader

了解EclipsePlugin 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方法就可以了。

PluginPluginClassLoader

简单demo准备,实现过程。

我们模拟几个重要的类是:

Plugin:插件类,描述每个具体的插件。

PluginDesciptor 插件描述符,记录了插件的IDNameVersion,依赖,扩展点等。

PluginManager:插件管理器,负责所有插件资源的管理,包括插件的启动,停止等。

PluginRegistry:插件注册表,提供了一个由插件IDplugin的映射。

Demo示例:

 

自定义插件类,派生于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>

 

<!--  定义两个扩展点PopupMenuMainMenu-->

   <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.

 

                     /*

                      * 得到插件描述符,描述符中记录了插件的IDNameVersion,依赖,扩展点等。

                      * 通过Plugin.xml文件得知,关于core的扩展点有两个:PopupMenuMainMenu。这两个扩展点都声

                      * 明了自己扩展的类和名称.Name 只是定义该扩展点的名称,Class则为了加载真正的功能。

                      */

                     core = pluginManager.getRegistry().getPluginDescriptor(

                                   "com.bjrongzhi.nms.client.plugins.core");

              } catch (JpfException e) {

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值