介绍 - 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关键字不需要强制重写
}