在应用程序启动时将实例注册为“单个" Bean [英] Registering an instance as 'singleton' bean at application startup
问题描述
我正在玩Spring Boot,并且我试图构造一个 ServiceImpl
的实例,以便在需要 Service
时进行解析.当前,我将实现注释为 @Component
,但这并没有给我提供构建所需实例的机会.
I am playing around with Spring Boot and I am trying to construct an instance of ServiceImpl
to be resolved when a Service
is required. Currently I am annotating the implementation as @Component
but this does not give me the chance to construct the instance as I want.
ServiceImpl
应该使用包含磁盘上文件路径的String构造.我想在应用程序的 @SpringBootApplication
类的main方法中执行此操作.
The ServiceImpl
should be constructed with a String containing a path to a file on disk. I would like to do this in the main method of the @SpringBootApplication
class of the application.
也许只是我来自一个很长的.NET背景,我们通常会像这样设置IoC容器:
Maybe it's just me coming from a long .NET background where we usually setup the IoC container like:
Service service = new Service("C:\\data.bin");
container.RegisterSingleton<IService>(service); // now whoever asks for a IService will receive this precise instance
在春季世界中,这有意义吗?
Does this make sense in Spring world?
LE:我很清楚GoF单例定义(即,防止其他人创建该类的实例)-我没有针对此目标.
LE: I am well aware of the GoF singleton definition (i.e. prevent everyone else from creating instances of the class) - I am not targeting this.
推荐答案
如注释中所述,可以通过将您的位置详细信息存储在配置文件中,然后在Spring Bean初始化时注入它们来完成此操作.
As described in the comment this can be done by storing your location details on a configuration file and then inject them upon Spring Bean initialization.
假设您的 application.properties
看起来像这样:
Assuming your application.properties
looks like this:
my.sample.config.A=somelocationA
my.sample.config.B=somelocationB
my.sample.config.C=somelocationC
my.sample.config.D.one=somelocationD1
my.sample.config.D.two=somelocationD2
下面我将演示实现此目的的4种方法:
Below I'm demo-ing 4 ways to do achieve this:
1 .通过直接在Bean方法创建时注入属性:
1.By injecting your property directly on the Bean method creation:
@Bean
public A myBeanA(@Value("${my.sample.config.A}") String myprop) {
System.out.println("from bean A with " + myprop);
return new A(myprop);
}
2 .通过将属性注入Config范围的变量并将其用于Bean方法创建中:
2.By injecting the property on a Config-wide variable and use that in your Bean method creation:
@Value("${my.sample.config.B}")
private String mylocationB;
//..
@Bean
public B myBeanB() {
System.out.println("from bean B with " + mylocationB);
return new B(mylocationB);
}
3 .通过将整个环境注入Config,然后手动选择所需的属性:
3.By injecting the whole environment in the Config and then hand-pick the property needed:
@Autowired
private Environment env;
//..
@Bean
public C myBeanC() {
String locationC = env.getProperty("my.sample.config.C");
System.out.println("from bean C with " + locationC);
return new C(locationC);
}
4 .这是Spring Boot的独占方式.您可以使用类型安全的配置属性直接用 @ConfigurationProperties
进行注释,您的bean定义了前缀命名空间,从此以后所有参数将自动映射到该bean中定义的属性!
4.This is a Spring Boot exclusive way. You can use Type-safe Configuration Properties annotating with @ConfigurationProperties
directly your bean defining a prefix-namespace and all params from that point onwards will be auto-mapped to the properties defined in that bean!
@ConfigurationProperties(prefix = "my.sample.config.D")
@Component
class D {
private String one;
private String two;
public String getOne() { return one; }
public void setOne(String one) {
System.out.println("from bean D with " + one);
this.one = one;
}
public String getTwo() { return two; }
public void setTwo(String two) {
System.out.println("from bean D with " + two);
this.two = two;
}
}
下面的整体一文件代码如下:
Below the overall one-file code in one piece:
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@SpringBootApplication
public class DemoApplication {
@Autowired
private Environment env;
@Value("${my.sample.config.B}")
private String mylocationB;
@Bean
public A myBeanA(@Value("${my.sample.config.A}") String myprop) {
System.out.println("from bean A with " + myprop);
return new A(myprop);
}
@Bean
public B myBeanB() {
System.out.println("from bean B with " + mylocationB);
return new B(mylocationB);
}
@Bean
public C myBeanC() {
String locationC = env.getProperty("my.sample.config.C");
System.out.println("from bean C with " + locationC);
return new C(locationC);
}
@ConfigurationProperties(prefix = "my.sample.config.D")
@Component
class D {
private String one;
private String two;
public String getOne() { return one; }
public void setOne(String one) {
System.out.println("from bean D with " + one);
this.one = one;
}
public String getTwo() { return two; }
public void setTwo(String two) {
System.out.println("from bean D with " + two);
this.two = two;
}
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
class A {
private final String location;
public A(String location) { this.location = location; }
}
class B {
private final String location;
public B(String location) { this.location = location; }
}
class C {
private final String location;
public C(String location) { this.location = location; }
}
}
这篇关于在应用程序启动时将实例注册为“单个" Bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!