1. 概述
本文将演示如何在 Spring 框架中注入 Java 集合类型,主要包括 List
、Map
和 Set
三大常用接口。
核心思路是:通过 Spring 的依赖注入机制,将集合实例或集合中的元素(包括普通值或 Bean 引用)自动装配到目标 Bean 中。这在处理多实现策略、插件化设计或配置集合化参数时非常实用。
✅ 掌握集合注入,能帮你更灵活地组织 Bean 之间的关系,避免硬编码。
2. 使用 @Autowired 注入 List
我们先定义一个包含 List<String>
字段的 Bean:
public class CollectionsBean {
@Autowired
private List<String> nameList;
public void printNameList() {
System.out.println(nameList);
}
}
这里使用了字段注入(field injection),通过 @Autowired
让 Spring 自动装配一个字符串列表。
接着在配置类中注册 CollectionsBean
,并提供一个 List<String>
类型的 Bean:
@Configuration
public class CollectionConfig {
@Bean
public CollectionsBean getCollectionsBean() {
return new CollectionsBean();
}
@Bean
public List<String> nameList() {
return Arrays.asList("John", "Adam", "Harry");
}
}
⚠️ 注意:Spring 会自动将所有类型匹配的 Bean 收集起来,注入到 List
中。这里的 nameList()
方法返回的 Bean 正好匹配 List<String>
类型。
测试代码:
ApplicationContext context = new AnnotationConfigApplicationContext(CollectionConfig.class);
CollectionsBean collectionsBean = context.getBean(CollectionsBean.class);
collectionsBean.printNameList();
输出结果:
[John, Adam, Harry]
3. 使用构造器注入 Set
现在我们改用 Set<String>
并采用构造器注入方式:
public class CollectionsBean {
private Set<String> nameSet;
public CollectionsBean(Set<String> strings) {
this.nameSet = strings;
}
public void printNameSet() {
System.out.println(nameSet);
}
}
构造器注入更利于不可变性和单元测试,属于推荐做法。
配置类中需要手动创建 Set
实例并传入构造器:
@Bean
public CollectionsBean getCollectionsBean() {
return new CollectionsBean(new HashSet<>(Arrays.asList("John", "Adam", "Harry")));
}
✅ 构造器注入时,Spring 不会自动聚合多个 Bean,需要开发者显式构造集合。
4. 使用 Setter 注入 Map
接下来演示 Map
类型的注入,使用 setter 方式:
public class CollectionsBean {
private Map<Integer, String> nameMap;
@Autowired
public void setNameMap(Map<Integer, String> nameMap) {
this.nameMap = nameMap;
}
public void printNameMap() {
System.out.println(nameMap);
}
}
在配置类中定义一个 Map<Integer, String>
类型的 Bean:
@Bean
public Map<Integer, String> nameMap(){
Map<Integer, String> nameMap = new HashMap<>();
nameMap.put(1, "John");
nameMap.put(2, "Adam");
nameMap.put(3, "Harry");
return nameMap;
}
调用 printNameMap()
后输出:
{1=John, 2=Adam, 3=Harry}
⚠️ 注意:Map 注入时,key 和 value 都由提供方决定,接收方只需类型匹配即可。
5. 注入 Bean 引用集合
更常见的场景是注入一组相同类型的 Bean 实例,比如多个策略实现类。
先定义一个简单 Bean:
public class BaeldungBean {
private String name;
public BaeldungBean(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
然后在 CollectionsBean
中注入 List<BaeldungBean>
:
public class CollectionsBean {
@Autowired(required = false)
private List<BaeldungBean> beanList;
public void printBeanList() {
System.out.println(beanList);
}
}
在配置类中注册多个 BaeldungBean
类型的 Bean:
@Configuration
public class CollectionConfig {
@Bean
public BaeldungBean getElement() {
return new BaeldungBean("John");
}
@Bean
public BaeldungBean getAnotherElement() {
return new BaeldungBean("Adam");
}
@Bean
public BaeldungBean getOneMoreElement() {
return new BaeldungBean("Harry");
}
}
Spring 会自动将所有 BaeldungBean
类型的 Bean 聚合成一个 List
并注入。
输出结果:
[John, Adam, Harry]
5.1 使用 @Order 控制 Bean 注入顺序
默认情况下,Bean 的注入顺序不确定。若需排序,可使用 @Order
注解:
@Configuration
public class CollectionConfig {
@Bean
@Order(2)
public BaeldungBean getElement() {
return new BaeldungBean("John");
}
@Bean
@Order(3)
public BaeldungBean getAnotherElement() {
return new BaeldungBean("Adam");
}
@Bean
@Order(1)
public BaeldungBean getOneMoreElement() {
return new BaeldungBean("Harry");
}
}
Spring 会按 @Order
值从小到大排序注入:
[Harry, John, Adam]
✅ @Order
在 AOP、监听器、集合注入等场景中都非常有用。
5.2 使用 @Qualifier 筛选特定 Bean
有时我们不想要所有 BaeldungBean
,只想注入其中一部分。这时可以用 @Qualifier
标记目标 Bean。
修改注入点:
@Autowired
@Qualifier("CollectionsBean")
private List<BaeldungBean> beanList;
并在配置类中标记目标 Bean:
@Configuration
public class CollectionConfig {
@Bean
@Qualifier("CollectionsBean")
public BaeldungBean getElement() {
return new BaeldungBean("John");
}
@Bean
public BaeldungBean getAnotherElement() {
return new BaeldungBean("Adam");
}
@Bean
public BaeldungBean getOneMoreElement() {
return new BaeldungBean("Harry");
}
}
此时只有被 @Qualifier("CollectionsBean")
标记的 getElement()
返回的 Bean 被注入。
测试输出:
[John]
✅ @Qualifier
是实现“按需注入”的利器,尤其适合多实现类共存的场景。
6. 设置空集合为默认值
有时候我们希望即使没有配置,也能拿到一个空集合而不是 null
,避免 NPE。
可以使用 @Value
结合 SpEL 设置默认值:
public class CollectionsBean {
@Value("${names.list:}#{T(java.util.Collections).emptyList()}")
private List<String> nameListWithDefaultValue;
public void printNameListWithDefaults() {
System.out.println(nameListWithDefaultValue);
}
}
${names.list:}
表示从配置文件读取names.list
,冒号后是默认值(空)。#{T(java.util.Collections).emptyList()}
是 SpEL 表达式,调用静态方法返回不可变空列表。
如果未在 application.properties
中设置 names.list
,输出为:
[]
⚠️ 注意:Collections.emptyList()
返回的是不可变集合。如果后续需要修改,建议用 new ArrayList<>()
包装。
7. 总结
本文系统演示了 Spring 中集合注入的多种方式:
- ✅
List
、Set
、Map
均可通过@Autowired
注入 - ✅ 支持字段、构造器、setter 三种注入方式,推荐构造器
- ✅ 可注入值类型集合,也可注入 Bean 引用集合
- ✅ 使用
@Order
控制注入顺序 - ✅ 使用
@Qualifier
实现精准筛选 - ✅ 通过 SpEL 设置默认空集合,避免
null
这些技巧在实际项目中非常实用,比如:
- 多个
Validator
实现注入List<Validator>
- 多个
Handler
按顺序执行 - 动态配置白名单、黑名单等
完整代码示例可参考:GitHub 项目地址