基本上要實現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