基本上要实现extensibility或插件的设计模式。有多种方式来实现这种情况。
您希望哪个组件可以允许其他人重新加载模块,定义一个接口并将您自己的实现作为默认实现来实现。例如,在这里,我想提供一个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{
//Add more classes if you want
}
loadedClass.add(f.getName());
}
}
}
在这一点上,你可以阅读定制实现和系统类加载器加载。现在你已经准备好了。这种方法存在安全隐患,您需要从互联网上学习。
我实现了一个示例代码并发布在github上,please take a look。快乐的编码!
http://www.beanshell.org/manual/embeddedmode.html – 2014-12-09 13:29:59
我想知道没有人提到OSGi。 http://en.wikipedia.org/wiki/OSGi – Yser 2014-12-15 13:19:48