200字
[编程] Java插件系统的设计
2024-11-13
2024-11-13

介绍 - Introduction

在我的项目 XiaoYuBotX 中,添加了插件系统。插件系统是一种热加载,在不修改主程序代码与不重启的情况下,给程序添加功能,这能减少重启程序、调试程序的次数,提高效率,增强程序的拓展性。

理论 - Theory

一般插件系统分为三个部分: 接口、插件、插件加载器 。插件按照接口编写程序处理数据, 插件加载器加载插件并按照接口说明调用函数。

插件

插件加载器

全部流程

代码 - Code

接口代码

package your.package.name;

public interface plugin {
    void onEnable();
    void onDisable();

    // 函数A 当事件A触发
    void functionA(String Data);

    // 使用default关键字不需要强制重写函数
    default void functionB() {}
}

插件加载器

package your.package.name;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

public class PluginLoader {
    private static List<Plugin> plugins = new ArrayList<>();

    public static void loadPlugins() {
        // 插件目录
        File dir = new File("plugins");
        if (dir.isDirectory()) {
            // 获取插件目录下所有.jar结尾的文件
            for (File file : dir.listFiles(f -> f.getName().endsWith(".jar"))) {
                try {
                    // 加载 .jar 文件
                    URL[] urls = { file.toURI().toURL() };
                    URLClassLoader classLoader = new URLClassLoader(urls);
                    
                    // 这里是插件的类名
                    // 可以给每个jar包内包含主类信息文件,例如我项目中的plugin.toml文件
                    // 里面记录了主类、插件名、版本等,可读取文件解析出主类名
                    Class<?> clazz = classLoader.loadClass("your.package.name.MyPlugin");
                    Plugin plugin = (Plugin) clazz.getDeclaredConstructor().newInstance();
                    // 启用插件
                    plugin.onEnable();
                    // 添加到插件列表
                    plugins.add(plugin);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
   // 当A事件触发时调用,也可以写一个获取插件列表并for调用
   public static void onEventA(String Data){
          for (Plugin plugin : plugins) {
            // 与接口内的方法对应
            plugin.functionA();
        }
   }
}


插件

package your.plugin.package.name;

import your.plugin.pluginInterface;

public class Example implements pluginInterface {
    @Override
    public void onEnable() {
        System.out.println("EchoPlugin is enabled!");
    }

    @Override
    public void onDisable() {
        System.out.println("EchoPlugin is disabled!");
    }

    // 函数A 当事件A触发
    @Override
    public void functionA(String Data) {
        System.out.println("Event A triggered!" + Data);
    }

    // 函数B同样写法,但由于使用default关键字不需要强制重写

}

Comment