如何在启动 Spring 引导时将 Java class 的实例提升为 Spring Bean?
How can I promote an instance of a Java class to a Spring Bean when launching Spring Boot?
启动 Spring 引导应用程序时,如何将 Java class 的实例动态传递给 Spring 配置?
我有一个 ThirdPartyService
在实例化时需要 SomeConfig
。现在,我想使用自定义 ServiceWrapper
包装此服务,然后使用 Spring Boot 以编程方式启动它,而不需要 ServiceWrapper
的用户知道 Spring Boot 是在幕后使用的,ServiceWrapperTest
让您了解我打算如何使用它:
@Service
public class ThirdPartyService {
private final SomeConfig someConfig;
@Autowired
public ThirdPartyService(final SomeConfig someConfig) {
this.someConfig = someConfig;
}
void start() {
// reads values from someConfig and starts the service
}
void stop() {
// stops the service
}
}
public class SomeConfig {
// getters and setters omitted
}
@SpringBootApplication
public class ServiceWrapper {
private ThirdPartyService thirdPartyService;
public ServiceWrapper() {
}
public void start(SomeConfig someConfig) {
// how can I pass someConfig to Spring Boot?
thirdPartyService = SpringApplication.run(ThirdPartyService.class).getBean(ThirdPartyService.class);
}
public void stop() {
if (thirdPartyService != null) {
thirdPartyService.stop();
}
}
}
class ServiceWrapperTest {
@Test
void testStartAndStop() {
SomeConfig someConfig = new SomeConfig();
ServiceWrapper serviceWrapper = new ServiceWrapper(someConfig);
serviceWrapper.start();
serviceWrapper.stop();
}
}
毫不奇怪,测试失败并出现以下错误:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.test.ThirdPartyService required a bean of type 'com.example.test.SomeConfig' that could not be found.
Action:
Consider defining a bean of type 'com.example.test.SomeConfig' in your configuration.
如何将 SomeConfig
实例传递给 Spring Beot 以便它符合自动装配的条件?是否可以使用 @Bean
、@Configuration
或类似的(我不这么认为)?
Spring 引导版本 2.6.1
你可以用 @Component 注释它,如果它只是第三方 class 并在 中执行标准构造函数或字段注入服务包装器。此外,自 Spring 5.2 以来,您不必使用 @Autowired.
显式注释依赖注入
@Service
public class ThirdPartyService {
private final SomeConfig someConfig;
public ThirdPartyService(final SomeConfig someConfig) {
this.someConfig = someConfig;
}
void start() {
// reads values from someConfig and starts the service
}
void stop() {
// stops the service
}
}
@Component
public class SomeConfig {
// getters and setters omitted
}
如果我理解正确的话。
你是这个意思吗:
@SpringBootApplication
public class ServiceWrapper {
@Bean
SomeConfig getSomeConfig() {
return someConfig;
}
private static SomeConfig someConfig; // really not thread safe
private ApplicationContext context;
public void start(SomeConfig someConfig) {
this.someConfig = someConfig;
this.context = SpringApplication.run(ServiceWrapper.class);
// do whatever you want with ThirdPartyService
ThirdPartyService service = this.context.getBean(ThirdPartyService.class);
}
public void stop() {
this.context.close();
}
}
这样您就可以使 SomeConfig 成为 Spring 的 bean 并使用它来连接您的上下文,但您不需要更改 SomeConfig 中的任何代码。然后您填充了 ThirdPartyService,您可以使用 getter.
return 它
您可以使用 ApplicationContextInitializer
使 SomeConfig
的现有实例可用作 bean:
public void start(SomeConfig someConfig) {
SpringApplication application = new SpringApplication(ServiceWrapper.class);
application.addInitializers(new ApplicationContextInitializer<ConfigurableApplicationContext>() {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.getBeanFactory().registerSingleton("someConfig", someConfig);
}
});
ThirdPartyService service = application.run().getBean(ThirdPartyService.class);
// Use service as needed
}
启动 Spring 引导应用程序时,如何将 Java class 的实例动态传递给 Spring 配置?
我有一个 ThirdPartyService
在实例化时需要 SomeConfig
。现在,我想使用自定义 ServiceWrapper
包装此服务,然后使用 Spring Boot 以编程方式启动它,而不需要 ServiceWrapper
的用户知道 Spring Boot 是在幕后使用的,ServiceWrapperTest
让您了解我打算如何使用它:
@Service
public class ThirdPartyService {
private final SomeConfig someConfig;
@Autowired
public ThirdPartyService(final SomeConfig someConfig) {
this.someConfig = someConfig;
}
void start() {
// reads values from someConfig and starts the service
}
void stop() {
// stops the service
}
}
public class SomeConfig {
// getters and setters omitted
}
@SpringBootApplication
public class ServiceWrapper {
private ThirdPartyService thirdPartyService;
public ServiceWrapper() {
}
public void start(SomeConfig someConfig) {
// how can I pass someConfig to Spring Boot?
thirdPartyService = SpringApplication.run(ThirdPartyService.class).getBean(ThirdPartyService.class);
}
public void stop() {
if (thirdPartyService != null) {
thirdPartyService.stop();
}
}
}
class ServiceWrapperTest {
@Test
void testStartAndStop() {
SomeConfig someConfig = new SomeConfig();
ServiceWrapper serviceWrapper = new ServiceWrapper(someConfig);
serviceWrapper.start();
serviceWrapper.stop();
}
}
毫不奇怪,测试失败并出现以下错误:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.test.ThirdPartyService required a bean of type 'com.example.test.SomeConfig' that could not be found.
Action:
Consider defining a bean of type 'com.example.test.SomeConfig' in your configuration.
如何将 SomeConfig
实例传递给 Spring Beot 以便它符合自动装配的条件?是否可以使用 @Bean
、@Configuration
或类似的(我不这么认为)?
Spring 引导版本 2.6.1
你可以用 @Component 注释它,如果它只是第三方 class 并在 中执行标准构造函数或字段注入服务包装器。此外,自 Spring 5.2 以来,您不必使用 @Autowired.
显式注释依赖注入@Service
public class ThirdPartyService {
private final SomeConfig someConfig;
public ThirdPartyService(final SomeConfig someConfig) {
this.someConfig = someConfig;
}
void start() {
// reads values from someConfig and starts the service
}
void stop() {
// stops the service
}
}
@Component
public class SomeConfig {
// getters and setters omitted
}
如果我理解正确的话。
你是这个意思吗:
@SpringBootApplication
public class ServiceWrapper {
@Bean
SomeConfig getSomeConfig() {
return someConfig;
}
private static SomeConfig someConfig; // really not thread safe
private ApplicationContext context;
public void start(SomeConfig someConfig) {
this.someConfig = someConfig;
this.context = SpringApplication.run(ServiceWrapper.class);
// do whatever you want with ThirdPartyService
ThirdPartyService service = this.context.getBean(ThirdPartyService.class);
}
public void stop() {
this.context.close();
}
}
这样您就可以使 SomeConfig 成为 Spring 的 bean 并使用它来连接您的上下文,但您不需要更改 SomeConfig 中的任何代码。然后您填充了 ThirdPartyService,您可以使用 getter.
return 它您可以使用 ApplicationContextInitializer
使 SomeConfig
的现有实例可用作 bean:
public void start(SomeConfig someConfig) {
SpringApplication application = new SpringApplication(ServiceWrapper.class);
application.addInitializers(new ApplicationContextInitializer<ConfigurableApplicationContext>() {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.getBeanFactory().registerSingleton("someConfig", someConfig);
}
});
ThirdPartyService service = application.run().getBean(ThirdPartyService.class);
// Use service as needed
}