Spring создает компонент вручную и регистрируется как синглтон - PullRequest
2 голосов
/ 05 октября 2019

Предположим, у меня есть такой компонент, как:

@Component
public class MyComponent {
    ...
}

Теперь я хочу создать экземпляр этого компонента вручную и сделать его одноэлементным, поэтому в своей основной функции я создаю новый контекст и затем создаюnew MyComponent и зарегистрируйте его как синглтон:

var context = new AnnotationConfigApplicationContext(AppConfig.class);
context.getBeanFactory().registerSingleton(MyComponent.class.getCanonicalName() + ".ORIGINAL", new MyComponent());
context.refresh();

Проблема, которую я обнаружил, состоит в том, что MyComponent все еще создается Spring, поэтому я не получаю ни одного экземпляракласса, но два.

Как я могу сделать эту работу?

Полный пример:

Основной класс:

package my.spring;

import static org.springframework.beans.factory.config.AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        context.getBeanFactory()
               .registerSingleton(MyComponent.class.getCanonicalName() + ORIGINAL_INSTANCE_SUFFIX,
                                  new MyComponent());

        MyComponent singleton = context.getBean(MyComponent.class); // This fails because there are now two such types

        primaryStage.setScene(new Scene(new VBox(20,
                                                 new TextArea("Hello Spring"),
                                                 new TextArea(singleton.myName))));
        primaryStage.setOnCloseRequest(w -> context.close());
        primaryStage.show();
    }
}

AppConfig.java

package my.spring;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class AppConfig {

}

MyComponent.java

package my.spring;

import org.springframework.stereotype.Component;

@Component
public class MyComponent {
    public final String myName = getClass().getCanonicalName();
}

Решение, которое я ищу, не должно включать filtering out MyComponent в сканировании компонента AppConfig. Я ищу динамическое решение, которое позволит мне сказать Spring не создавать определенные синглтоны, когда они уже существуют в графе зависимостей.

Возможно ли это или нет?

1 Ответ

2 голосов
/ 05 октября 2019

Вот различные решения для этого:

1) Удалите аннотацию @Component из вашего класса `` MyComponent`.

2) Определите интерфейс и введите его там, где вам нужно, в качестве интерфейса. В вашем коде создайте и внедрите интерфейс типа '... registerSingleton (..., new MyComponentImpl ())'.

Следующие подходы не соответствуют всем вашим требованиям, но я бы посоветовал вам рассмотретьих тоже.

3) Если ваша цель - просто зарегистрировать компонент с определенным именем, рассмотрите возможность использования @Component("MyName").

4) Используйте класс конфигурации (помеченный @Configuration),В методе, который предоставляет компонент типа MyComponent, создайте свой компонент вручную. Здесь вы не регистрируете бин вручную, но все же у вас есть контроль над созданием бина. Например, вы можете инициализировать его по-разному в зависимости от некоторых параметров конфигурации или даже создавать экземпляры разных подклассов.

5) Реализовать фабрику, которая будет создавать этот компонент. Опять же, вы не будете вводить его напрямую. Но вы будете иметь полный контроль над созданием вашего компонента.

Если вы сообщите нам, чего вы на самом деле пытаетесь достичь, могут быть и другие решения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...