По сути, вы хотите реализовать расширяемость или шаблон дизайна плагина. Есть несколько способов реализовать этот сценарий.
Какой бы компонент вы ни хотели позволить кому-то еще перезагрузить модуль, определить интерфейс и реализовать свою собственную реализацию по умолчанию. Например, здесь я пытаюсь предоставить 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, пожалуйста, посмотрите. Удачного кодирования!
person
kamoor
schedule
14.12.2014