java - Spring手动创建组件并注册为单例

标签 java spring-boot javafx

假设我有一个组件,例如:

@Component
public class MyComponent {
    ...
}

现在,我想手动实例化这个组件并使其成为单例,所以在我的主要函数中,我创建了一个新的上下文,然后创建了一个新的 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 {

}

我的组件.java

package my.spring;

import org.springframework.stereotype.Component;

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

我正在寻找的解决方案不应涉及在AppConfig 组件扫描中过滤MyComponent。我正在寻找一个动态解决方案,它可以让我告诉 spring 不要创建某些单例,当它们已经存在于依赖关系图中时。

这可能吗?

最佳答案

这里有不同的解决方案:

1) 从您的类 ``MyComponent` 中删除注释 @Component

2) 定义接口(interface),将其作为接口(interface)注入(inject)到你需要的地方。在您的代码中创建和实现接口(interface),例如“... registerSingleton(..., new MyComponentImpl())”。

以下方法不能满足您的所有要求,但我建议您也考虑一下。

3) 如果您的目标只是注册一个具有特定名称的组件,请考虑使用@Component("MyName")

4) 使用配置类(用@Configuration注解)。在提供 MyComponent 类型 bean 的方法中手动创建您的 bean。在这里您没有手动注册 bean,但您仍然可以控制 bean 的创建。例如,您可以根据某些配置参数对其进行不同的初始化,或者您甚至可以创建不同子类的实例。

5) 实现将创建此 bean 的工厂。同样,您不会直接注入(inject)它。但是您将完全控制 bean 的创建。

如果您告诉我们您实际想要实现的目标,还可以有其他解决方案。

关于java - Spring手动创建组件并注册为单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58243489/

相关文章:

java - 在 Java RESTful 资源中获取用户信息

java - 无法弄清楚为什么我会得到不兼容的类型

java - 带有 JPARepository (MySQL) 的 Spring Boot 应用程序无法启动

java - 如何为 ADFS 配置 spring boot security OAuth2?

database - 为什么我的千分尺在应用程序启动后只执行一次?

JavaFx TableView 行失去选择突出显示

java - java中的快速随机文件访问

java - Maven 项目 : SWT 3. 5 依赖 : any official public repo?

JavaFX:如何不在 ScrollingPane 中的标签的圆形边框之外填充背景

java - 为什么 javafx 应用程序无法使用 Platform.runLater 启动以及为什么会因 lambda 表达式而挂起?