gpt4 book ai didi

java - 我可以使用代码来控制 Spring Boot 中 ApplicationContext 做出的依赖解析决策吗?

转载 作者:行者123 更新时间:2023-11-30 01:44:41 25 4
gpt4 key购买 nike

我在 Spring Boot 中使用 Autowiring 将接口(interface)的实现注入(inject)到标记为组件的类中。有时我需要使用某些接口(interface)的特定实现来运行应用程序(和/或测试)。我知道这可以通过注释组合(@Qualifier@Primary 等)来完成,但这些不适合我的需求。我希望能够(可选)编写在 ApplicationContext 确定将创建我的接口(interface)的哪些实现之前运行的代码,并在该代码中覆盖其中一个或多个决策。

我尝试使用这样的代码:

context.registerBean(MyService.class, () -> new MyService());

如下所述:https://www.baeldung.com/spring-5-functional-beans .

但是我无法在代码中找到足够早插入此内容的位置,以便它会影响应用程序中的所有 Autowiring 字段。特别是这是测试中的一个问题(标记为@SpringBootTest)。

我希望能够使用类似于 C# 中的代码:

在一个测试中,我可能会使用此代码,然后运行测试:

container.Register<IDataLayer, MockDataLayer>();
container.Register<IPersistenceLayer, FilePersistenceLayer>();

在另一个测试中,我可能会使用此代码,然后运行测试:

container.Register<IDataLayer, SQLDataLayer>();
container.Register<IPersistenceLayer, MockPersistenceLayer>();

在生产中我可能会运行这个

container.Register<IDataLayer, SQLDataLayer>();
container.Register<IPersistenceLayer, FilePersistenceLayer>();

或者简单地依赖文件配置。

是否可以对 ApplicationContext 所做的选择创建这种级别的控制,或者我必须依赖注释和 xml 配置文件的脆弱选择来使我的每个测试完全按照我的需要运行?

最佳答案

Functional beans是Spring 5的一个新特性,它更适合将函数注册为bean提供者。如果您只需要基于代码的配置,则不需要去那里,而是可以使用标准的 Spring 基于注释的配置。

常规、标准 Spring javaconfig

简单示例,配置类:

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

@Configuration
public class ApplicationConfiguration {

@Bean
public DemoManager helloWorld()
{
return new DemoManagerImpl();
}
}

主类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

这将使用组件扫描来查找您的配置类,然后调用其方法来获取 bean。您可以提供所需的配置类作为参数,您提到的 SpringBootTest 也支持这一点。

因此,在测试时,您可以使用自己的测试配置,然后自定义加载哪些 Bean 并提供其他 Bean。如果配置类是嵌套类,则甚至不需要指定它:

@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringBootDemoApplicationTests
{
@Test
public void testSomething() {
// ...
}

@TestConfiguration
static class MyTestConfiguration {

//tests specific beans
@Bean
DataSource createDataSource(){
//
}
}
}

使用@TestConfiguration将添加到您的配置中 - 如果您不想添加而是完全替换配置,请使用@SpringBootTest(classes = YourCustomConfiguration.class) .

替代方案:使用 spring javaconfig 手动创建应用程序上下文

如果您不想使用 javaconfig 或组件扫描,而是想“自己”注册您的配置类,您可以这样做,例如在主类中使用这种 main 方法:

public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);

HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
helloWorld.setMessage("Hello World!");
helloWorld.getMessage();
}

不常用,但也没有错。

替代方案 2:手动应用程序上下文、手动 Bean 注册

如果你真的想避免配置类,你也可以这样做:

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SomeClass {
public static void main(String args[]) {

// first, we create empty context ourselves
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext();

// then we get its bean factory to be able to register stuff
ConfigurableListableBeanFactory beanFactory = ctx.getBeanFactory();

// register our bean
YourBean beanToRegister = new YourBean();
beanFactory.registerSingleton(beanToRegister.getClass().getCanonicalName(), beanToRegister);

ctx.refresh(); // context refresh actually updates the status

// here we can test a bean was actually created and working
YourBean helloWorld = ctx.getBean(YourBean.class);
helloWorld.setAuthor("Hello World!");
System.out.println(helloWorld.getAuthor());
}
}

与其他替代方案一样,这不是 Spring 的常见方法,但也没有错。

关于java - 我可以使用代码来控制 Spring Boot 中 ApplicationContext 做出的依赖解析决策吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58577294/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com