有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

SpringJava配置扩展抽象配置

在我们的软件中,我们使用SpringJava配置。我们有一个设置,其中一个配置扩展了一个抽象配置。请看一下这个测试用例:


    import java.util.concurrent.atomic.AtomicInteger;
    import org.junit.Test;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    public class SpringConfigTest {

      @Test
      public void test() {
        final AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
        ctx.getBeansOfType(AtomicInteger.class).entrySet().stream().forEach(
            b -> System.out.println(b.getKey() + " : " + b.getValue() + " (" + b.getValue().hashCode() + ")"));
      }

      @Configuration
      public static class MyConfig extends AbstractConfig {

        @Bean(name = "anotherName")
        public AtomicInteger myBean() {
          return new AtomicInteger(5);
        }
      }

      public static abstract class AbstractConfig {

        @Bean
        public AtomicInteger myBean() {
          return new AtomicInteger(10);
        }
      }
    }

其思想是MyConfig覆盖AbstractConfig,并且在创建的ApplicationContext中只有一个名为anotherName的类型为AtomicInteger的bean

结果是:

anotherName : 5 (2109798150)
myBean : 5 (1074389766)

所以它说,有两个bean(两个实例,每个名称一个),更令人惊讶的是,使用相同的方法(MyConfig#myBean())创建了这两个bean

这种行为在我们看来很奇怪:我们期望spring要么尊重java的常规继承方式,要么只从MyConfig创建bean。。。或者至少创建两个独立的bean(“10”和“5”),以防它将AbstractConfig视为独立的配置

在研究此问题时,我们还尝试在MyConfig类上注册方法名:


public static class MyConfig extends AbstractConfig {

    @Bean(name = ["anotherName", "myBean"])
    public AtomicInteger myBean() {
    ...

这次我们只有一个豆子: anotherName : 5 (2109798150)

。。更让我们惊讶的是

有人知道这是正确的行为还是我们只是用错了?我们应该在春天的吉拉举行一场音乐会吗? 提前谢谢


共 (2) 个答案

  1. # 1 楼答案

    在春季,bean可以先按类型连接,然后按名称连接。 因此@Qualifier(“myBeanName”)可以消除自动连接多个具有相同类型的bean的歧义,例如

    因此: 非抽象bean被赋予了另一个名称,这使得它在应用程序上下文中被视为不同的bean

    您可以在非配置类中声明bean。这称为“lite”模式,但在应用程序上下文中它仍然是一个bean。 另请参见thislite模式的答案

    我不知道可以给一个bean多个名称,但是由于Springbean在默认情况下是单例的,所以在第二种情况下,应该只创建一个bean,因为“myBean”已经存在,并且应用程序上下文中只能有一个具有该名称的bean

  2. # 2 楼答案

    我不是Spring专业人士,但我要说,这种行为是出于设计。为了实现您想要的(我希望我猜对了)“注入这个bean而不是另一个”,您将在bean上使用@Primary,根据您将使用@Conditional@Profile的情况有选择地启用配置