假设我有一个组件,例如:
@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/