【问题标题】:How can I achieve annotation-based collection merging in Spring?如何在 Spring 中实现基于注解的集合合并?
【发布时间】:2019-10-22 17:17:44
【问题描述】:

我正在尝试使用一组特定类型的所有 bean 初始化一个 Spring 组件(真的,我可以迭代的任何东西)。

Spring 核心文档讨论了collection merging,但仅在基于注解的配置上下文中。

假设我有以下配置

@Configuration
public class MyConfig {
    @Bean
    public SomeInterface single() {
        return new SomeInterface() {};
    }

    @Bean
    public Set<SomeInterface> multi() {
        return Collections.singleton(
            new SomeInterface() {}
        );
    }
}

接口在哪里定义

public interface SomeInterface {}

我希望这个组件获得两个 bean 的聚合 - 一些包含两个匿名类的集合。

@Component
public class MyComponent {
    public MyComponent(Set<SomeInterface> allInterfaces) {
        System.out.println(allInterfaces.size()); // expecting 2, prints 1
    }
}

我明白为什么 Spring 会达到它的结果;它看到这个方法需要一个Set&lt;SomeInterface&gt;,而MyConfig::multi 是一个Set&lt;SomeInterface&gt; 类型的bean,所以它会自动装配。

如果我将签名更改为Collection&lt;SomeInterface&gt;,它会自动与MyConfig::single 绑定。再一次,我明白了原因:没有什么完全匹配的,但是有 SomeInterface 类型的 bean(在这种情况下,只有一个),所以它构造了它们的临时集合并用它自动装配。很好,但不是我想要的。

我希望解决方案是可扩展的,这样如果添加另一个 bean,依赖组件就不需要更改。我试过使用两个参数,每个参数都有一个@Qualifier,这可以工作但不可扩展。

我怎样才能让它工作?

【问题讨论】:

    标签: java spring dependency-injection spring-bean


    【解决方案1】:

    正如您已经提到的,MyConfig::multiSet&lt;SomeInterface&gt; 类型的 bean,因此自动装配 Collection&lt;Set&lt;SomeInterface&gt;&gt; 将为您提供所有这些集合。以下应该工作

    public MyComponent(Collection<SomeInterface> beans,
                       Collection<Set<SomeInterface>> beanSets) {
        // merge both params here
    }
    

    如果您需要多个地方的所有实现,定义另一个包含合并集合的 bean 并自动装配该 bean 可能是有意义的:

    static class SomeInterfaceCollection {
        final Set<SomeInterface> implementations;
    
        SomeInterfaceCollection(Set<SomeInterface> implementations) {
            this.implementations = implementations;
        }
    }
    
    @Bean
    public SomeInterfaceCollection collect(Collection<SomeInterface> beans,
            Collection<Collection<SomeInterface>> beanCollections) {
        final HashSet<SomeInterface> merged = ...
        return new SomeInterfaceCollection(merged);
    }
    

    【讨论】:

    • 这不是一个坏主意。我希望将来能够公开List&lt;SomeInterface&gt; 并将其包括在内。我想Collection&lt;Collection&lt;...&gt;&gt; 可以解决这个问题
    • List> list??
    猜你喜欢
    • 1970-01-01
    • 2015-03-25
    • 2021-09-09
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 2012-09-08
    • 2023-03-06
    • 2018-05-29
    相关资源
    最近更新 更多