spring - 提供列表的@Bean-method 被忽略,如果有一个@Bean-method 证明单个bean

标签 spring autowired

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

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

我将其归结为一个配置:如果我提供一个 bean 和一个 bean 列表,将仅使用一个 bean

这在以下测试中重现。它失败了,因为列表只包含“A”和“D”(这表明它没有 Autowiring beans 列表):

@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 的模块(将它们 Autowiring 为列表)应该 Autowiring 所有 bean。

我怎样才能让它运行? Spring 的行为在什么情况下有意义?

最佳答案

我可以通过引入 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 的行为是一致的:

As you defined a bean of type List it will be used. Autowiring is based on type, it will try to detect the bean of the certain type. The collection (and map as well) is a special one looking up all dependencies of the given type.

关于spring - 提供列表的@Bean-method 被忽略,如果有一个@Bean-method 证明单个bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59344999/

相关文章:

java - 在 Spring Beans 中初始化字段的正确方法是什么?

java - @autowiring 没有被注入(inject)

spring - 在 Oracle AS 10g 上部署后的 Servlet 初始化错误

java - Spring MVC 3 - @ResponseBody 方法如何呈现 JSTLView?

java - Spring Boot Weblogic 12c JNDI 数据源 : injection not working gives NullPointerException

java - spring+JPA EntityManager注入(inject)service和dao

java - 如何解决Spring boot中的 "spring crudrepository bean not found"?

java - 如何在 Spring Boot 项目 : 上正确配置 Intellij IDEA 中的 jRebel

java - 如何在 spring jpa 中组合 4 个表(查询)

java - 我可以 Autowiring 适配器类吗?