Итак, у меня есть проект, в котором я использую загрузку Spring, и хочу использовать систему модулей.Я хочу, чтобы система модулей была динамически перезагружаемой.У меня это почти работает, но @ComponentScan полностью не работает в модулях.
Существует папка модуля, содержащая файлы JAR, которые загружаются при запуске, и их необходимо динамически выгружать, загружать и перезагружать.
Модули создаются через AnnotationConfigApplicationContext, загрузчик классов контекста устанавливается на загрузчик классов ядра, а класс @Configuration, предоставляемый методом в интерфейсе модуля, регистрируется через context.register.
Объявления @Bean в @Configuration работают для autowire, и все классы загружаются правильно.Проблема в том, что @ComponentScan не работает.Я даже пытался аннотировать класс с @Component, у которого нет поля или чего-либо еще, и он выдает ошибку автопровода, как будто это не в контексте.Это не было бы таким большим делом, если бы это не было проблемой с моими репозиториями.
Если есть способ, которым я могу вручную запускать компонентное сканирование без аннотаций, я в порядке, выполняя эту дополнительную работу,
Я пытался использовать весенний загрузочный пакет с @SpringBootApplication (scanPackages = {"package.name"}
@ EnableJpaRepository @ EntityScan
все в соответствующих местахи имеют правильные параметры.
Я пытался использовать .register с основным контекстом, который не работал. Я не могу использовать это в любом случае, так как вы можете отменить регистрацию конфигурации, насколько я могу судить.
Это мой код, который на самом деле загружает файл jar
public Module loadModule(Path path) throws Exception {
if (!path.toFile().exists()) {
throw new Exception(String.format("Could not find module at %s", path.toAbsolutePath()));
}
JarFile file = new JarFile(path.toFile());
ZipEntry moduleJson = file.getEntry("module.json");
System.out.println(path.toUri().toURL());
if (moduleJson == null) {
throw new Exception(String.format("Could not find module json at %s", path.toAbsolutePath()));
}
String moduleJsonSTR = CharStreams
.toString(new InputStreamReader(file.getInputStream(moduleJson), Charsets.UTF_8));
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.setPrettyPrinting().create();
PluginConfig config = gson.fromJson(moduleJsonSTR, PluginConfig.class);
URLClassLoader classLoader = new URLClassLoader(new URL[] { path.toUri().toURL() },
getClass().getClassLoader());
Class mainClass = classLoader.loadClass(config.getMain());
Enumeration<JarEntry> entries = file.entries();
while (entries.hasMoreElements()) {
JarEntry clazz = entries.nextElement();
if (clazz.getName().equals(mainClass.getName())) {
System.out.println("FOUND MAIN AND SKIPPING");
continue;
}
if (clazz.isDirectory() || !clazz.getName().endsWith(".class")) {
continue;
}
String className = clazz.getName().substring(0, clazz.getName().length() - 6);
className = className.replace('/', '.');
classLoader.loadClass(className);
}
Module module = (Module) mainClass.newInstance();
System.out.println(module.getConfigurationClass().getName());
module.setName(config.getName());
file.close();
classLoader.close();
return module;
}
Это мой код, который инициализирует контекст
public AnnotationConfigApplicationContext initializeContext() {
SpringConfig cfg = getSpringConfig();
this.context = new AnnotationConfigApplicationContext();
this.context.setClassLoader(Core.class.getClassLoader());
this.context.refresh();
this.context.register(getConfigurationClass());
Map<String, Object> props = context.getEnvironment().getSystemProperties();
cfg.getProperties().forEach((key, value) -> props.put(key, value));
return context;
}
Есть бин, который является пустымкласс с @Component, который автоматически подключается к классу, в котором контекст автоматически подключается без проблем. Поэтому я знаю, что autowire работает, я знаю, что он управляется пружиной, но @ComponentScan не работает.
Я бы хотелЛибо получите работу ComponentScan, либо найдите способ ручного добавления компонентов программным способом.
Дополнительный код:
Базовый плагин: Это мой класс модуля: https://hastebin.com/potayuqali.java Этотроллер, который загружает указанные модули: https://hastebin.com/ipegaqojiv.java Пример модуля:
Это пример одного из модулей: https://hastebin.com/umujiqepob.java Это @configuration для этого модуля: https://hastebin.com/lakemucifo.css