Fondamentalmente si desidera implementare extensibility o plug-in design pattern. Esistono diversi modi per implementare questo scenario.
Quale che sia il componente che si desidera consentire a qualcun altro di ricaricare il modulo, definire un'interfaccia e implementare la propria implementazione come predefinita.Ad esempio, qui sto cercando di fornire una HelloInterface che ogni paese può realizzare e caricare in qualsiasi momento,
public interface HelloInterface {
public String sayHello(String input);
..
}
public class HelloImplDefault implements HelloInterface {
public String sayHello(String input) {
return "Hello World";
}
}
Ora consentire all'utente di aggiungere un plugin (un'implementazione personalizzata) i file in un percorso pre-configurato. È possibile utilizzare FileSystemWatcher o un thread in background per analizzare questo percorso e provare a compilare e caricare il file.
Per compilare il file 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();
}
Per caricare file di classe,
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());
}
}
}
A questo punto è possibile leggere un'implementazione personalizzata e caricati in classe sistema di caricamento. Ora sei pronto per andare. Ci sono implicazioni sulla sicurezza di questo approccio che devi imparare da internet.
Ho implementato un codice di esempio e pubblicato in github, please take a look. Buona programmazione!
http://www.beanshell.org/manual/embeddedmode.html –
Mi chiedo se nessuno abbia menzionato OSGi. http://en.wikipedia.org/wiki/OSGi – Yser