Spring java配置扩展了一个抽象配置

时间:2016-09-19 12:46:01

标签: java spring spring-java-config

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


    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中,名称AtomicInteger下只有一个anotherName类型的bean。

结果是:

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

所以它说,有两个bean(两个实例 - 每个名称一个) - 甚至更多的是:使用相同的方法(MyConfig#myBean())来创建它们。

这种行为对我们来说很奇怪:我们期望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)

..对我们来说更令人惊讶的是。

有人知道这是否真的是正确的行为,还是我们只是错误地使用它?我们应该在春天的jira上提票吗? 提前谢谢!

2 个答案:

答案 0 :(得分:1)

我不是春天职业选手,但我说这种行为是设计的。为了实现你想要的东西(我希望我猜对了)"注入这个豆而不是其他的#34;您可以在bean上使用@Primary,根据您使用@Conditional的情况选择性地启用配置,即@Profile

答案 1 :(得分:0)

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

所以: 非抽象Bean被赋予另一个名称这一事实使它在应用程序上下文中被视为另一个Bean。

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

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