Как мы можем гарантировать, что один контекст Spring зависит от другого для совместного использования bean-компонентов?JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Как мы можем гарантировать, что один контекст Spring зависит от другого для совместного использования bean-компонентов?

Сообщение Anonymous »

В настоящее время я разрабатываю сервер Minecraft, используя ответвление API Spigot (PaperMc). Этот API изначально не поддерживает внедрение зависимостей, поэтому я интегрировал библиотеку Spring-Context в свои плагины, чтобы воспользоваться преимуществами внедрения зависимостей.
У меня есть первый плагин, который служит в качестве API для других моих плагинов. Этот плагин имеет собственный контекст Spring. Я начал разработку второго плагина, который должен извлекать bean-компоненты из первого плагина и добавлять их в свой собственный контекст. В данном случае это пул соединений HikariCP.
Для управления контекстами моих плагинов я создал интерфейс PluginContextManager, который содержит следующий код:

Код: Выделить всё

import lombok.NonNull;
import lombok.val;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import static com.github.badpop.hildir.common.colors.HildirColors.LOG_COLOR;
import static net.kyori.adventure.text.Component.text;

/**
* Utility interface used to build a plugin's context in order to take advantage of dependency injection.
*/
public interface PluginContextManager {

/**
* Constructs an instance of a PluginContext which will allow dependencies to be injected.
*
* @param plugin           the main class of the plugin (the one that extends JavaPlugin).
* @param customBeans      an iterable containing all the customs beans to be added to the context
* @param componentClasses Register one or more component classes to be processed.
* @param               the main class of the plugin (the one that extends JavaPlugin).
* @return a new JavaPlugin instance
*/
static  PluginContext buildPluginContext(@NotNull @NonNull T plugin,
@Nullable Iterable... componentClasses) {
return new PluginContext(plugin, customBeans, componentClasses);
}

/**
* Constructs an instance of a PluginContext which will allow dependencies to be injected.
*
* @param plugin           the main class of the plugin (the one that extends JavaPlugin).
* @param customBeans      an iterable containing all the customs beans to be added to the context
* @param componentClasses Register one or more component classes to be processed.
* @param               the main class of the plugin (the one that extends JavaPlugin).
* @return a new JavaPlugin instance
*/
static  PluginContext buildPluginContext(@NotNull @NonNull T plugin,
@Nullable Iterable... componentClasses) {
return new PluginContext(plugin, customBeans, parentContext, componentClasses);
}

class PluginContext extends AnnotationConfigApplicationContext {

private PluginContext(T plugin, Iterable...  componentClasses) {
super();

plugin.getComponentLogger().info(text("Building %s context...".formatted(plugin.toString())).color(LOG_COLOR));

setDisplayName(plugin + " plugin context");

val beanFactory = getBeanFactory();
beanFactory.registerSingleton("plugin", plugin);
beanFactory.registerSingleton("logger", plugin.getComponentLogger());

if (customBeans != null) {
customBeans.forEach(customBean -> beanFactory.registerSingleton(customBean.beanName(), customBean.beanInstance()));
}

register(componentClasses);
refresh();

plugin.getComponentLogger().info(text("%s context successfully built !".formatted(plugin.toString())).color(LOG_COLOR));
}

private  PluginContext(T plugin, Iterable... componentClasses) {
super();
plugin.getComponentLogger().info(text("Building %s context...".formatted(plugin.toString())).color(LOG_COLOR));

setDisplayName(plugin + " plugin context");
setId(plugin.getName() + "_plugin_context");
setParent(parentContext);

val beanFactory = getBeanFactory();
beanFactory.registerSingleton("plugin", plugin);
beanFactory.registerSingleton("logger", plugin.getComponentLogger());

if (customBeans != null) {
customBeans.forEach(customBean -> beanFactory.registerSingleton(customBean.beanName(), customBean.beanInstance()));
}

register(componentClasses);
refresh();

plugin.getComponentLogger().info(text("%s context successfully built !".formatted(plugin.toString())).color(LOG_COLOR));
}
}

record CustomBean(String beanName, T beanInstance) {
}
}
Мой первый плагин создает свой собственный контекст с помощью этой инструкции: context = PluginContextManager.buildPluginContext(this, пустойList(), HildirApiConfiguration.class);.
Во втором плагине я хочу определить контекст первого плагина как родительский для его контекста:

Код: Выделить всё

//Retrieve the first plugin main class
val hildirApi = (HildirApi) Bukkit.getServer().getPluginManager().getPlugin("hildir-api");
if (hildirApi == null) {
getComponentLogger().error(text("Unable to enable hildir-people... Is the hildir-api plugin installed ?").color(RED));
getServer().getPluginManager().disablePlugin(this);
}

//setting the first plugin's context as parent of the new context
peopleContext = PluginContextManager.buildPluginContext(this, emptyList(), hildirApi.getContext(), HildirPeopleConfiguration.class);
Наконец, в моем классе HildirPeopleConfiguration я объявляю компонент, который должен использовать один из компонентов в родительском контексте:

Код: Выделить всё

//A bean of type HikariConnectionPool is already present in the parent context
@Bean
public TestCommand testCommand(HikariConnectionPool hikariConnectionPool) {
return new TestCommand(hikariConnectionPool);
}
Однако, когда я запускаю свой сервер с двумя установленными на нем плагинами, второй плагин не может создать свой контекст с этой трассировкой стека:

Код: Выделить всё

[20:43:25 ERROR]: Error occurred while enabling hildir-people v1.0.0-SNAPSHOT (Is it up to date?)
java.lang.LinkageError: loader constraint violation: loader 'hildir-people-1.0.0-SNAPSHOT.jar' @29b08d69 wants to load class com.github.badpop.hildir.common.dependencyinjection.PluginContextManager$PluginContext. A different class with the same name was previously loaded by 'hildir-api-1.0.0-SNAPSHOT.jar' @77c05f35.  (com.github.badpop.hildir.common.dependencyinjection.PluginContextManager$PluginContext is in unnamed module of loader 'hildir-api-1.0.0-SNAPSHOT.jar' @77c05f35, parent loader java.net.URLClassLoader @421faab1)
at java.lang.ClassLoader.defineClass1(Native Method) ~[?:?]
at java.lang.ClassLoader.defineClass(ClassLoader.java:1027) ~[?:?]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:243) ~[paper-api-1.20.4-R0.1-SNAPSHOT.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:593) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:169) ~[paper-api-1.20.4-R0.1-SNAPSHOT.jar:?]
at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:164) ~[paper-api-1.20.4-R0.1-SNAPSHOT.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:526) ~[?:?]
at com.github.badpop.hildir.common.dependencyinjection.PluginContextManager.buildPluginContext(PluginContextManager.java:46) ~[hildir-people-1.0.0-SNAPSHOT.jar:?]
at com.github.badpop.hildirpeople.HildirPeople.buildPluginContext(HildirPeople.java:58) ~[hildir-people-1.0.0-SNAPSHOT.jar:?]
at com.github.badpop.hildirpeople.HildirPeople.onEnable(HildirPeople.java:42) ~[hildir-people-1.0.0-SNAPSHOT.jar:?]
at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:287) ~[paper-api-1.20.4-R0.1-SNAPSHOT.jar:?]
at io.papermc.paper.plugin.manager.PaperPluginInstanceManager.enablePlugin(PaperPluginInstanceManager.java:188) ~[paper-1.20.4.jar:git-Paper-496]
at io.papermc.paper.plugin.manager.PaperPluginManagerImpl.enablePlugin(PaperPluginManagerImpl.java:104) ~[paper-1.20.4.jar:git-Paper-496]
at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:507) ~[paper-api-1.20.4-R0.1-SNAPSHOT.jar:?]
at org.bukkit.craftbukkit.v1_20_R3.CraftServer.enablePlugin(CraftServer.java:639) ~[paper-1.20.4.jar:git-Paper-496]
at org.bukkit.craftbukkit.v1_20_R3.CraftServer.enablePlugins(CraftServer.java:550) ~[paper-1.20.4.jar:git-Paper-496]
at net.minecraft.server.MinecraftServer.loadWorld0(MinecraftServer.java:671) ~[paper-1.20.4.jar:git-Paper-496]
at net.minecraft.server.MinecraftServer.loadLevel(MinecraftServer.java:431) ~[paper-1.20.4.jar:git-Paper-496]
at net.minecraft.server.dedicated.DedicatedServer.initServer(DedicatedServer.java:309) ~[paper-1.20.4.jar:git-Paper-496]
at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1131) ~[paper-1.20.4.jar:git-Paper-496]
at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:319) ~[paper-1.20.4.jar:git-Paper-496]
at java.lang.Thread.run(Thread.java:1583) ~[?:?]
Я также старался не делать второй контекст зависимым от первого, программно извлекая bean-компоненты из первого контекста и добавляя их «вручную» во второй контекст. Но это тоже не работает...
Как мы можем гарантировать, что один контекст Spring зависит от другого для совместного использования bean-компонентов?

Подробнее здесь: https://stackoverflow.com/questions/785 ... to-share-b
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»