问题
java
实现动态从jar
包加载插件并运行.
实现
定义插件运行的接口,用户需要自己实现的
public interface PluginService { /** * 插件运行方法 */ void process(); }
定义插件实体类
@Data public class Plugin { /** * 插件名称 */ private String pluginName; /** * jar包完整路径 */ private String jarPath; /** * class完整路径 */ private String className; }
定义插件异常
public class PluginException extends Exception { public PluginException(String message) { super(message); } }
定义插件管理类
@Data @NoArgsConstructor public class PluginManager { private Map<String, Class> clazzMap = new HashMap<>(); public PluginManager(List<Plugin> plugins) throws PluginException { initPlugins(plugins); } public void initPlugin(Plugin plugin) throws PluginException { try { // URL url = new URL("file:" + plugin.getJarPath()); URL url = new File(plugin.getJarPath()).toURI().toURL(); URLClassLoader classLoader = new URLClassLoader(new URL[]{url}); Class clazz = classLoader.loadClass(plugin.getClassName()); clazzMap.put(plugin.getClassName(), clazz); } catch (Exception e) { throw new PluginException("plugin " + plugin.getPluginName() + " init error," + e.getMessage()); } } public void initPlugins(List<Plugin> plugins) throws PluginException { for (Plugin plugin : plugins) { initPlugin(plugin); } } public PluginService getInstance(String className) throws PluginException { Class clazz = clazzMap.get(className); Object instance = null; try { instance = clazz.newInstance(); } catch (Exception e) { throw new PluginException("plugin " + className + " instantiate error," + e.getMessage()); } return (PluginService) instance; } }
定义插件配置文件
<!-- 采用xml方式存储配置,dom4j解析 --> <dependency> <groupId>org.dom4j</groupId> <artifactId>dom4j</artifactId> <version>2.1.1</version> </dependency>
public class PluginXmlParser {
public static List<Plugin> getPluginList() throws PluginException {
List<Plugin> list = new ArrayList<>();
SAXReader saxReader = new SAXReader();
Document document = null;
try {
document = saxReader.read(new File("plugin.xml"));
} catch (Exception e) {
throw new PluginException("read plugin.xml error," + e.getMessage());
}
Element root = document.getRootElement();
List<?> plugins = root.elements("plugin");
for (Object pluginObj : plugins) {
Element pluginEle = (Element) pluginObj;
Plugin plugin = new Plugin();
plugin.setPluginName(pluginEle.elementText("name"));
plugin.setJarPath(pluginEle.elementText("jar"));
plugin.setClassName(pluginEle.elementText("class"));
list.add(plugin);
}
return list;
}
}
运行测试类
public class Main { public static void main(String[] args) throws PluginException { // 从配置文件加载插件 List<Plugin> pluginList = PluginXmlParser.getPluginList(); PluginManager pluginManager = new PluginManager(pluginList); for (Plugin plugin : pluginList) { PluginService pluginService = pluginManager.getInstance(plugin.getClassName()); System.out.println("开始执行[" + plugin.getPluginName() + "]插件..."); // 调用插件 pluginService.process(); System.out.println("[" + plugin.getPluginName() + "]插件执行完成"); } // 动态加载插件 Plugin plugin = new Plugin(); plugin.setPluginName("B插件"); plugin.setJarPath("D:\\flinkDemo\\java8\\out\\artifacts\\test\\test.jar"); plugin.setClassName("com.deri.stream.plugina.PluginB"); pluginManager.initPlugin(plugin); PluginService pluginService = pluginManager.getInstance("com.deri.stream.plugina.PluginB"); pluginService.process(); } }
插件A/B/C
public class PluginA implements PluginService { @Override public void process() { System.out.println("Plugin A."); } }
public class PluginB implements PluginService {
@Override
public void process() {
System.out.println("Plugin B.");
}
}
public class PluginC implements PluginService {
@Override
public void process() {
System.out.println("Plugin C.");
}
}
- 插件配置文件
<?xml version="1.0" encoding="UTF-8"?> <plugins> <plugin> <name>A插件</name> <jar>D:\flinkDemo\java8\out\artifacts\test\test.jar</jar> <class>com.deri.stream.plugina.PluginA</class> </plugin> </plugins>