基本上,您想要实现可扩展性或插件设计模式。有多种方法可以实现此场景。
无论您想要允许其他人重新加载模块的组件是哪个,都要定义一个接口并将自己的实现作为默认实现。例如,这里我正在尝试提供一个HelloInterface,每个国家都可以实现并随时加载。
public interface HelloInterface {
public String sayHello(String input);
..
}
public class HelloImplDefault implements HelloInterface {
public String sayHello(String input) {
return "Hello World";
}
}
现在允许用户将插件(自定义实现)文件添加到预配置路径。您可以使用FileSystemWatcher或后台线程扫描此路径并尝试编译和加载文件。
要编译Java文件,
private void compile(List<File> files) throws IOException{
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager
.getJavaFileObjectsFromFiles(files);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null,
null, compilationUnits);
boolean success = task.call();
fileManager.close();
}
加载类文件,
private void load(List<File> files) throws MalformedURLException, InstantiationException, IllegalAccessException, ClassNotFoundException{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
for(File f: files){
if(f.getName().endsWith(".class") && !loadedClass.contains(f.getName())){
URL url = f.toURL();
URL[] urls = new URL[]{url};
Object obj = cl.loadClass(f.getName().replace(".class", "")).newInstance();
if(obj instanceof HelloInterface){
HelloProviders.addProvider((HelloInterface)obj);
System.out.println("Loaded "+ ((HelloInterface)obj).getProviderName());
}else{
}
loadedClass.add(f.getName());
}
}
}
此时,您可以阅读自定义实现并加载到系统类加载器中。现在您已经准备好了。这种方法存在安全隐患,您需要从互联网上学习相关知识。
我实现了一个示例代码并发布在Github上,请查看。祝编码愉快!