Java SPI机制实现插件化扩展功能

Java SPI机制实现插件化扩展功能

1.背景

我们有一个图数据库的服务,用户希望在不修改现有源代码的情况下扩展自定义的分词器,达到可插件式扩展功能的目标。

通过Java的SPI机制实现插件式的扩展功能还是比较简便的,下面分主程序部分和插件实现2部分来说明。

特别的,在实现过程中遇到一个比较怪异的问题:ServiceLoader.load()时抛出NoClassDefFoundError异常,经过Google及StackOverflow都没能找到原因,问题表现与这几个链接中描述的类似:serviceloader-issue-in-jettyserviceloader-in-glassfish4-java-ee-appserviceloader-next-causing-a-noclassdeffounderror
文末会记录一下这个问题的解决过程及原因分析。

2.SPI插件实现要素

主程序部分主要包括:

  1. 定义插件接口
  2. 加载插件实现的Jar包
  3. 加载插件实现类对象

插件实现部分主要包括:

  1. 实现插件接口
  2. 配置SPI入口
  3. 打Jar包

3.实现插件化的流程

下面以扩展一个分词器实例来说明插件化的流程。

  1. 定义接口
    定义接口com.baidu.hugegraph.plugin.HugeGraphPlugin,内容如下:
    public interface HugeGraphPlugin {
         
      public String name();
      public void register();
      public String supportsMinVersion();
      public String supportsMaxVersion();
    }
    
  2. 加载插件实现的Jar包
    参考SPI官方文档,我们定义了一个目录plugins来存放插件的Jar包,在启动Java主程序服务时通过参数-Djava.ext.dirs=plugins指定插件Jar包的目录。当需要扩展新的插件时,只需要把插件Jar包拷贝到plugins目录下,重启主程序服务即可生效。完整的启动命令示例:
    java -Djava.ext.dirs=plugins -Dname="HugeGraphServer" ${JAVA_OPTIONS} -cp ${CP}:${CLASSPATH} com.baidu.hugegraph.dist.HugeGraphServer ${APP_ARGS}
    
  3. 加载插件实现类实例
    在主程序中,我们通过ServiceLoader来加载所有插件实例。
    private static void registerPlugins() {
         
      LOG.info("Loading plugins...");
      ServiceLoader<HugeGraphPlugin> plugins = ServiceLoader.load(HugeGraphPlugin.class);
      for (HugeGraphPlugin plugin : plugins) {
         
        LOG.info("Loading plugin {}({})",
                 plugin.name(), plugin.getClass().getCanonicalName());
        try {
         
          plugin.register();
          LOG.info("Loaded plugin {}", plugin.name())
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值