当前位置: 代码网 > it编程>编程语言>Java > 在Spring中注入Set集合的方法详解

在Spring中注入Set集合的方法详解

2026年09月17日 Java 我要评论
一、什么是 set 注入?set 注入是指将一个 set 类型的集合注入到 bean 的属性中。set 与 list 最大的区别是:set 中的元素不允许重复,且通常不保证顺序(除非使用 linked

一、什么是 set 注入?

set 注入是指将一个 set 类型的集合注入到 bean 的属性中。set 与 list 最大的区别是:set 中的元素不允许重复,且通常不保证顺序(除非使用 linkedhashsettreeset)。

@component
public class mybean {
    private set<string> servers;          // 字符串 set
    private set<datasource> datasources;  // bean set
    private set<handler> handlers;        // 策略/处理器 set
}

在 spring 注入场景中,set 常用于:

  • 需要去重的多个同类型依赖
  • 配置文件中定义的多个值(不关心顺序)
  • 收集所有实现类时避免重复

二、xml 配置中注入 set

2.1 注入字符串 set

<bean id="mybean" class="com.example.mybean">
    <property name="servers">
        <set>
            <value>server1.example.com</value>
            <value>server2.example.com</value>
            <value>server3.example.com</value>
        </set>
    </property>
</bean>

2.2 注入 bean set

<bean id="mybean" class="com.example.mybean">
    <property name="datasources">
        <set>
            <ref bean="datasource1"/>
            <ref bean="datasource2"/>
            <ref bean="datasource3"/>
        </set>
    </property>
</bean>

2.3 注入基本类型 set

<bean id="mybean" class="com.example.mybean">
    <property name="ports">
        <set>
            <value>8080</value>
            <value>8081</value>
            <value>8082</value>
        </set>
    </property>
</bean>

spring 会自动将字符串值转换为 integer 类型。

2.4 注入对象 set

<bean id="mybean" class="com.example.mybean">
    <property name="users">
        <set>
            <bean class="com.example.user">
                <property name="name" value="张三"/>
                <property name="age" value="25"/>
            </bean>
            <bean class="com.example.user">
                <property name="name" value="李四"/>
                <property name="age" value="30"/>
            </bean>
        </set>
    </property>
</bean>

2.5<set>与<list>的 xml 差异

<!-- set 类型属性 -->
<property name="servers">
    <set>
        <value>server1</value>
        <value>server2</value>
    </set>
</property>
<!-- list 类型属性 -->
<property name="servers">
    <list>
        <value>server1</value>
        <value>server2</value>
    </list>
</property>

虽然 xml 标签不同,但 spring 会根据目标属性的类型自动选择合适的集合实现。如果属性是 set,即使写 <list>,spring 也会注入 set(通常是 linkedhashset)。

三、@value 注入 set

3.1 从配置文件读取

@component
public class mybean {
    
    // 配置文件:app.servers=server1,server2,server3
    @value("${app.servers}")
    private set<string> servers;
    
    // 带默认值
    @value("${app.ports:8080,8081,8082}")
    private set<integer> ports;
}

配置文件:

app:
  servers: server1,server2,server3
  ports: 8080,8081,8082

spring 会自动将逗号分隔的字符串拆分为 set。

3.2 使用 spel 拆分

@value("#{'${app.servers}'.split(',')}")
private set<string> servers;

注意:split() 返回数组,spring 会自动转换为 set。如果数组中有重复元素,set 会自动去重。

3.3 直接指定多个值

@value("server1,server2,server3")
private set<string> servers;

四、@configurationproperties 绑定 set

4.1 简单 set

@component
@configurationproperties(prefix = "app")
@getter
@setter
public class appproperties {
    private set<string> servers;
    private set<integer> ports;
}
app:
  servers:
    - server1
    - server2
    - server3
  ports: [8080, 8081, 8082]

4.2 对象 set

@component
@configurationproperties(prefix = "app")
@getter
@setter
public class appproperties {
    private set<user> users;
    
    @getter
    @setter
    public static class user {
        private string name;
        private int age;
        private string email;
    }
}
app:
  users:
    - name: 张三
      age: 25
      email: zhangsan@example.com
    - name: 李四
      age: 30
      email: lisi@example.com

4.3 嵌套 set

@component
@configurationproperties(prefix = "app")
@getter
@setter
public class appproperties {
    private set<cluster> clusters;
    
    @getter
    @setter
    public static class cluster {
        private string name;
        private set<string> nodes;  // 嵌套 set
    }
}
app:
  clusters:
    - name: cluster-a
      nodes:
        - node1
        - node2
    - name: cluster-b
      nodes:
        - node3
        - node4

五、自动注入 bean set(最常用)

spring 支持将容器中所有同类型的 bean 自动注入到 set 中。

5.1 基本用法

public interface paymentstrategy {
    void pay(double amount);
}

@component
public class alipaystrategy implements paymentstrategy {
    @override
    public void pay(double amount) {
        system.out.println("支付宝支付:" + amount);
    }
}

@component
public class wechatpaystrategy implements paymentstrategy {
    @override
    public void pay(double amount) {
        system.out.println("微信支付:" + amount);
    }
}

@component
public class paymentservice {
    
    @autowired
    private set<paymentstrategy> strategies;  // 自动注入所有实现
    
    public void payall(double amount) {
        strategies.foreach(s -> s.pay(amount));
    }
}

5.2 构造器注入 set

@service
public class paymentservice {
    private final set<paymentstrategy> strategies;
    
    public paymentservice(set<paymentstrategy> strategies) {
        this.strategies = strategies;
    }
}

5.3 set 的默认实现类型

spring 注入 set 时,默认使用 linkedhashsetlinkedhashset 内部维护了一个链表,保留了元素的插入顺序,因此注入到 set 中的 bean 顺序通常是 bean 定义的顺序。

如果需要去重且不关心顺序,可以声明为 set。如果需要排序,可以声明为 sortedsettreeset

@autowired
private sortedset<paymentstrategy> strategies;  // 按自然顺序排序

@autowired
private treeset<paymentstrategy> strategies;    // 按 comparator 或自然顺序

5.4 使用 @order 控制顺序

虽然 set 通常不保证顺序,但 linkedhashset 会保留插入顺序。配合 @order 注解,可以控制注入顺序:

@component
@order(1)
public class firststrategy implements paymentstrategy { }

@component
@order(2)
public class secondstrategy implements paymentstrategy { }

@component
@order(3)
public class thirdstrategy implements paymentstrategy { }

注入的 linkedhashset 中,元素按 @order 的值从小到大排列。

六、set 的自动去重特性

set 最重要的特性是元素去重。当容器中有多个相同类型的 bean 时,如果 bean 的 equals()hashcode() 判定为相同,set 会自动去重。

@component
public class handlera implements handler {
    @override
    public boolean equals(object obj) {
        return obj instanceof handlera;
    }
    
    @override
    public int hashcode() {
        return handlera.class.hashcode();
    }
}

@component
public class handlera2 implements handler {
    // 如果 equals 和 hashcode 与 handlera 相同,set 会去重
}

但在实际开发中,不同的 bean 通常不会互相 equals,所以 set 注入的去重效果主要体现在同一个 bean 被多次注册的场景(比如通过不同的配置方式重复注册)。

七、set 为空时的处理

7.1 默认行为

当容器中没有匹配类型的 bean 时,@autowired 注入 set 不会抛异常,而是注入一个空 set。

@autowired
private set<handler> handlers;  // 没有 handler 时,注入空 set(不是 null)

这与 list 注入行为一致。数组注入在找不到 bean 时会抛异常,而 set 和 list 会返回空集合。

7.2 使用 objectprovider 控制

@autowired
private objectprovider<set<handler>> handlersprovider;

public void dosomething() {
    set<handler> handlers = handlersprovider.getifavailable(collections::emptyset);
}

7.3 校验 set 不为空

@postconstruct
public void init() {
    if (strategies.isempty()) {
        throw new illegalstateexception("没有可用的策略实现");
    }
}

八、set 注入 vs list 注入 vs 数组注入

对比维度setlist数组
是否去重✅ 自动去重❌ 允许重复❌ 允许重复
是否有序⚠️ 取决于实现类✅ 有序✅ 有序
默认实现linkedhashsetarraylist
找不到 bean 时注入空 set注入空 list抛异常
排序支持支持 @order(linkedhashset)支持 @order支持 @order
适用场景需要去重的多实现需要顺序遍历固定长度、性能敏感

选择建议:

  • 需要去重且不关心顺序 → set
  • 需要顺序遍历 → list
  • 固定长度且性能敏感 → 数组
  • 需要按名称查找 → map

九、set 注入的底层实现

spring 在 populatebean() 阶段处理 set 注入时,会根据目标属性的类型选择合适的集合实现类。

简化流程:

  1. spring 扫描到 set<paymentstrategy> 类型的依赖
  2. 调用 defaultlistablebeanfactory.resolvemultiplebeans() 获取所有 paymentstrategy 类型的 bean
  3. 根据目标类型 set 选择合适的实现类(默认 linkedhashset
  4. 遍历所有匹配的 bean,依次添加到 set 中
  5. 将构建好的 set 赋值给目标字段

如果 bean 的数量为 0,返回空 set,不抛异常。

十、常见问题

10.1 set 注入为 null

原因:没有使用 @autowired 或没有 @component 注解。

解决:确保类被 spring 管理,字段标注 @autowired

10.2 set 顺序不符合预期

原因hashset 不保证顺序,如果 spring 注入的是 linkedhashset,则按 bean 定义的顺序。

解决:使用 @order 注解明确顺序,或声明为 sortedsettreeset

10.3 set 去重导致 bean 丢失

原因:多个 bean 的 equals()hashcode() 判定为相同,set 自动去重。

解决:检查 bean 的 equals()hashcode() 实现,避免误判。如果不希望去重,改用 list 或数组。

10.4 @value 注入 set 时逗号被拆分

原因:配置值中的逗号被当作分隔符。

解决:使用 @configurationproperties 绑定,或用 spel 自定义拆分。

10.5 set 与 @order 的配合

set 本身不保证顺序,但 linkedhashset 保留了插入顺序。如果使用 hashset@order 可能失效。

解决:声明为 set 时 spring 默认注入 linkedhashset,配合 @order 可以控制顺序。

十一、最佳实践

优先使用自动注入 set。 当需要收集同一接口的所有实现且需要去重时,@autowired set<t> 是最简洁的方式。

用 @order 控制顺序。 当 set 中的元素有执行顺序要求时,给实现类加 @order 注解。

配置文件中的 set 用 @configurationproperties。@value 更类型安全,支持嵌套对象。

处理空 set。@postconstruct 中校验关键 set 是否为空,避免业务逻辑出错。

注意 set 的去重特性。 如果多个 bean 的 equals() 判定相同,set 会去重。确认这是否符合业务预期。

选择合适的具体实现。 如果需要排序,声明为 sortedsettreeset;如果需要保留插入顺序,使用默认的 linkedhashset

十二、总结

维度核心要点
xml 注入使用 <set> 标签,支持嵌套、对象、基本类型
@value 注入逗号分隔字符串自动拆分,或使用 spel
@configurationproperties原生支持复杂 set 绑定,推荐用于配置文件
自动注入 bean set注入容器中所有同类型 bean,自动去重
默认实现linkedhashset(保留插入顺序)
顺序控制@order 注解配合 linkedhashset
空 set 处理默认注入空集合,需要时用 @postconstruct 校验
set vs listset 去重,list 允许重复;set 顺序取决于实现,list 天然有序
最佳实践自动注入用 set,配置绑定用 @configurationproperties,需要排序用 sortedset

set 注入是 spring 集合注入的重要形式,特别适合需要去重的多实现场景。理解 set 与 list 的区别、默认实现类的选择以及 @order 的配合,能让你在业务开发中更准确地选择集合类型,写出更符合语义的代码。

以上就是在spring中注入set集合的方法详解的详细内容,更多关于spring注入set集合的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com