如果存在@Bean方法来证明单个bean,则@Bean方法提供一个列表将被忽略

时间:2019-12-15 14:48:50

标签: spring autowired

我有一个提供单个bean的配置和一个提供一个bean列表的配置。所有这些bean具有相同的类型。

使用这些配置启动应用程序上下文时,我看到Bean类型的自动装配列表仅包含单个Bean。 我希望它包含该类型的所有bean。我使用Spring 5.2.0。

我将其简化为一种配置:如果我提供一个bean和一个bean列表,将仅使用单个bean

在以下测试中将其复制。失败,因为列表仅包含“ A”和“ D”(表明它没有自动装配bean列表):

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { TestConfiguration.class })
class AutowiringListsTest {

    @Autowired
    private List<TestBean> testBeanList;

    @Test
    void testThatBothConfigurationsContributeToBeanList() {
        final List<String> idList = testBeanList.stream().map(TestBean::getId).sorted().collect(Collectors.toList());
        assertThat(idList, hasItems("A", "B", "C", "D"));
    }

    @Configuration
    public static class TestConfiguration {

        @Bean
        public TestBean someBean() {
            return new TestBean("A");
        }

        @Bean
        public List<TestBean> someMoreBeans() {
            return Arrays.asList(new TestBean("B"), new TestBean("C"));
        }

        @Bean
        public TestBean anotherBean() {
            return new TestBean("D");
        }
    }

    public static class TestBean {

        private final String id;

        public TestBean(final String id) {
            this.id = id;
        }

        private String getId() {
            return id;
        }
    }
}

我想让它运行,以便多个模块可以提供某种类型的bean。

  • 某些模块想要提供多个bean,其数量取决于属性。
  • 某些模块将始终提供一个bean。
  • 使用bean的模块(将其自动装配为列表)应自动装配所有bean。

如何运行此程序?在什么情况下,Spring的行为有意义?

1 个答案:

答案 0 :(得分:0)

我可以通过引入TestBeanFactory来解决此问题。每个要贡献到TestBean列表的配置都提供了一个工厂。

@Configuration
public static class TestConfiguration {

    /** Implemented once in the configuration that defines <code>TestBean</code>. */
    @Bean
    public List<TestBean> testBeansFromFactory(Collection<TestBeanFactory> factories) {
        return factories.stream().map(TestBeanFactory::createTestBeans).flatMap(Collection::stream)
                .collect(toList());
    }

    // Further methods can be defined in various configurations that want to add to the list of TestBeans.

    @Bean
    public TestBeanFactory someBean() {
        return () -> Arrays.asList(new TestBean("A"));
    }

    @Bean
    public TestBeanFactory someMoreBeans() {
        return () -> Arrays.asList(new TestBean("B"), new TestBean("C"));
    }

    @Bean
    public TestBeanFactory anotherBean() {
        return () -> Arrays.asList(new TestBean("D"));
    }
}

public static class TestBean { ... }

public static interface TestBeanFactory {

    public Collection<TestBean> createTestBeans();
}

那行得通,而且只是更多的代码。

M.Deinum在评论中指出了Spring的行为是一致的:

  

在定义List类型的bean时,将使用它。自动装配基于类型,它将尝试检测特定类型的Bean。集合(以及地图)是一个特殊的集合,用于查找给定类型的所有依赖项。