问题
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>