it编程 > 编程语言 > Java

Spring 注入 List 集合详解:用法、原理与实战

6人参与 2026-09-17 Java

一、什么是 list 注入?

list 注入是指将一个 list 类型的集合注入到 bean 的属性中。与数组注入不同,list 更灵活——元素可以动态增删,支持泛型,是 spring 开发中处理多个同类型依赖的首选方式。

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

二、xml 配置中注入 list

2.1 注入字符串 list

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

2.2 注入 bean list

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

2.3 注入基本类型 list

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

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

2.4 注入嵌套 list

<bean id="mybean" class="com.example.mybean">
    <property name="matrix">
        <list>
            <list>
                <value>1</value>
                <value>2</value>
            </list>
            <list>
                <value>3</value>
                <value>4</value>
            </list>
        </list>
    </property>
</bean>

对应 java:

private list<list<integer>> matrix;

2.5 注入对象 list

<bean id="mybean" class="com.example.mybean">
    <property name="users">
        <list>
            <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>
        </list>
    </property>
</bean>

2.6 list 与 array 的 xml 差异

<!-- list 类型属性 -->
<property name="servers">
    <list>
        <value>server1</value>
        <value>server2</value>
    </list>
</property>
<!-- array 类型属性(spring 会自动转换) -->
<property name="servers">
    <array>
        <value>server1</value>
        <value>server2</value>
    </array>
</property>

虽然 <list><array> 语义不同,但对 list 类型的属性来说,两者都能使用。

三、@value 注入 list

3.1 从配置文件读取

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

配置文件:

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

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

3.2 使用 spel 拆分

当值中包含逗号或需要更复杂的拆分逻辑时,用 spel:

@value("#{'${app.servers}'.split(',')}")
private list<string> servers;
@value("#{'${app.servers:server1,server2}'.split(',')}")
private list<string> serverswithdefault;

3.3 直接指定多个值

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

四、@configurationproperties 绑定 list

4.1 简单 list

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

4.2 对象 list

@component
@configurationproperties(prefix = "app")
@getter
@setter
public class appproperties {
    private list<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 嵌套 list

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

4.4 list + map 组合

@component
@configurationproperties(prefix = "app")
@getter
@setter
public class appproperties {
    private list<database> databases;
    @getter
    @setter
    public static class database {
        private string type;
        private map<string, string> config;  // list 中嵌套 map
    }
}
app:
  databases:
    - type: mysql
      config:
        url: jdbc:mysql://localhost:3306/db1
        username: root
    - type: postgresql
      config:
        url: jdbc:postgresql://localhost:5432/db2
        username: admin

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

spring 支持将容器中所有同类型的 bean 自动注入到 list 中,这是策略模式在 spring 中的经典应用。

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 list<paymentstrategy> strategies;  // 自动注入所有实现
    public void payall(double amount) {
        strategies.foreach(s -> s.pay(amount));
    }
}

5.2 构造器注入 list

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

5.3 使用 @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 { }

注入的 list 中,元素按 @order 的值从小到大排列。也可以用 ordered 接口:

@component
public class firststrategy implements paymentstrategy, ordered {
    @override
    public int getorder() {
        return 1;
    }
}

5.4 策略模式实战:按名称分发

public interface paymentstrategy {
    string getname();
    void pay(double amount);
}
@component
public class alipaystrategy implements paymentstrategy {
    @override
    public string getname() { return "alipay"; }
    @override
    public void pay(double amount) {
        system.out.println("支付宝支付:" + amount);
    }
}
@component
public class wechatpaystrategy implements paymentstrategy {
    @override
    public string getname() { return "wechat"; }
    @override
    public void pay(double amount) {
        system.out.println("微信支付:" + amount);
    }
}
@service
public class paymentservice {
    private final map<string, paymentstrategy> strategymap;
    public paymentservice(list<paymentstrategy> strategies) {
        this.strategymap = strategies.stream()
            .collect(collectors.tomap(paymentstrategy::getname, s -> s));
    }
    public void pay(string type, double amount) {
        paymentstrategy strategy = strategymap.get(type);
        if (strategy == null) {
            throw new illegalargumentexception("不支持的支付方式:" + type);
        }
        strategy.pay(amount);
    }
}

六、list 为空时的处理

6.1 默认行为

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

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

这与数组注入不同——数组注入在找不到 bean 时会抛异常,而 list 注入会返回空集合。

6.2 使用 objectprovider 控制

@autowired
private objectprovider<list<handler>> handlersprovider;
public void dosomething() {
    list<handler> handlers = handlersprovider.getifavailable(collections::emptylist);
    // 使用 handlers
}

6.3 校验 list 不为空

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

七、list 注入 vs 数组注入 vs map 注入

对比维度list数组map
类型list<t>t[]map<string, t>
长度可变固定可变
找不到 bean 时注入空 list抛异常(默认)注入空 map
排序@order@order
按名称查找需手动转换需手动转换直接按 key 获取
适用场景需要顺序、遍历处理固定长度、性能敏感需要按名称查找

map 注入的用法:

@autowired
private map<string, paymentstrategy> strategymap;

spring 会自动将 bean 名称作为 key,bean 实例作为 value 注入到 map 中。这种方式在策略模式中比 list 更方便——直接按名称获取策略,不需要遍历。

八、常见问题

8.1 list 注入为 null

原因:没有使用 @autowired 或没有 @component 注解,或者类没有被 spring 管理。

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

8.2 list 顺序不符合预期

原因:多个 bean 注入 list 时,默认顺序是 bean 定义的顺序。

解决:使用 @order 注解明确指定顺序。

8.3 @value 注入 list 时逗号被拆分

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

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

@value("#{'${app.servers}'.split(';')}")  // 用分号分隔
private list<string> servers;

8.4 list 中混入 null

xml 配置中可以用 <null/> 注入 null 元素:

<list>
    <value>server1</value>
    <null/>
    <value>server3</value>
</list>

但建议避免在 list 中放入 null,容易导致空指针。

8.5 list 注入与 @qualifier 冲突

@qualifier 用于指定单个 bean 的名称,不能用于筛选 list 中的 bean。如果需要按条件筛选 bean,使用 @bean 方法手动组装,或使用 objectprovider

九、最佳实践

优先使用自动注入 list。 当需要收集同一接口的所有实现时,@autowired list<t> 是最简洁的方式,天然支持策略模式。

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

考虑使用 map 代替 list。 如果主要目的是按名称获取特定策略,直接注入 map<string, t> 更方便。

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

处理空 list。 虽然 list 注入不会抛异常,但空集合可能导致业务逻辑出错。在 @postconstruct 中校验关键 list 是否为空。

十、总结

维度核心要点
xml 注入使用 <list> 标签,支持嵌套、对象、基本类型
@value 注入逗号分隔字符串自动拆分,或使用 spel 自定义拆分
@configurationproperties原生支持复杂 list 绑定,推荐用于配置文件
自动注入 bean list注入容器中所有同类型 bean,策略模式的经典实现
顺序控制@order 注解或 ordered 接口
空 list 处理默认注入空集合,需要时用 objectprovider@postconstruct 校验
list vs maplist 适合遍历,map 适合按名称查找
最佳实践自动注入用 list,配置绑定用 @configurationproperties,按名称用 map

list 注入是 spring 中最常用的集合注入方式。它天然支持策略模式,让“收集所有实现类”变得极其简单。掌握 list 注入的各种方式,能让你在业务开发中灵活处理多实现、多配置的场景。

到此这篇关于spring 注入 list 集合详解的文章就介绍到这了,更多相关spring 注入 list 集合内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

MyBatis实现列表查询优化的实用技巧分享

09-17

Java为什么说只有值传递没有引用传递详解

09-17

Java Android线程池实践指南及高频问题

09-17

SpringBoot中Jackson高级用法教学:序列化脱敏、日期格式统一与流式JSON性能优化

09-17

JVM性能调优之GC日志分析与参数优化法则详解

09-17

Java基于EasyExcel实现动态表头Excel导出工具类的完整示例代码

09-17

猜你喜欢

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

发表评论