一种java运行时动态加载外部插件的方法

 需求

        一个服务程序(jar),定义了一些RPC的服务,希望能实现在运行时动态加载外部某个目录下的jar,运行某个特定服务。


 为什么需要插件模式

  • 解耦。特定服务的实现与服务框架解耦,便于独立开发、维护和拓展。
  • 可选。缩小服务模块的体积。实际业务不必要的服务可裁剪。
  • 开放。开发人员可自行开发服务实现,放在插件目录。

思路

  • 插件协议:所有的插件模式一定有一套协议,由插件的调用方和实现方共同遵守。这个协议考虑用Java的SPI实现。

  • 动态加载:通过自定义类加载器加载外部目录下的jar。


具体实现(https://github.com/tianshanfz/java-plugin-demo

  • 定义插件接口。例:PluginInterface.java
public interface PluginInterface {
    int sayHello(String name);
}
  • 实现插件。创建插件工程,实现插件接口,然后根据Java SPI的规则,在resources目录下创建META-INF/services目录,并以插件接口命名,内容为实现接口的类名。例:

  • 在插件调用方工程中,创建类加载器,加载插件目录下所有jar例:
File dir = new File(PLUGIN_DIR);
File[] files = dir.listFiles();
ArrayList<URL> urls = new ArrayList<URL>();
for (File file : files) {
    if (file.getName().endsWith(".jar")) {
       System.out.println("loading new plugin " + file.getAbsolutePath() + "...");
       urls.add(file.toURI().toURL());
    } 
}
int validSize = urls.size();
System.out.println("totally load " + validSize + " plugin jars." );
pluginClassLoader = new URLClassLoader(urls.toArray(new URL[validSize]) );
  • 在需要调用插件的地方,通过ServiceLoader加载指定接口的插件
PluginInterface ret = null;
ServiceLoader<PluginInterface> demoServiceLoader = ServiceLoader.load(PluginInterface.class,pluginClassLoader);
Iterator<PluginInterface> it = demoServiceLoader.iterator();
while (it.hasNext()) {
    ret = it.next();
    System.out.println("new demo plugin found: " + ret.getClass().getName()); 
}

  结尾

本文仅记录了一种可行的支持动态加载插件的方案,如有更合理的方案或者不当之处,欢迎讨论。

demo代码https://github.com/tianshanfz/java-plugin-demo

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值