Java中 Collections 工具类在 Spring 框架 Bean 属性注入不可变集合的运用

作者:袖梨 2026-07-14
Spring集合注入默认生成可变集合,不可变性需开发者手动封装(如Collections.unmodifiableList或List.copyOf),XML配置不支持自动不可变,推荐构造注入+final字段保障不可变语义。

Java 中 Collections 工具类本身不直接参与 Spring 的 Bean 属性注入,也不能用于创建「Spring 可识别的不可变集合」来完成属性注入。真正起作用的是 Spring 容器对集合类型(ListSetMap)的 XML 或注解配置支持,而不可变性需由开发者主动保障——Collections.unmodifiableXXX() 是运行时防护手段,不是注入机制的一部分。

Spring 集合注入本质是可变容器

Spring 在解析 <list><set><map> 等标签时,底层默认创建的是标准可变集合(如 ArrayListLinkedHashSetLinkedHashMap)。即使你写:

  • <list><value>a</value><value>b</value></list>
  • Spring 仍会注入一个普通 ArrayList,而非 Collections.unmodifiableList(...)

这意味着:注入后若业务代码调用 list.add(...),不会报错——它确实是可变的。

想实现不可变集合,必须手动包装

若需注入后即不可修改,应在 Bean 初始化阶段完成封装。常见做法有两种:

立即学习“Java免费学习笔记(深入)”;

  • 在 setter 方法中封装public void setRoles(List<String> roles) { this.roles = Collections.unmodifiableList(new ArrayList<>(roles)); }
  • 在构造函数中封装(推荐)**: public UserService(List<String> permissions) { this.permissions = Collections.unmodifiableList(permissions); } 注意:此时需确保传入的 permissions 是副本(避免外部仍持有原始引用),否则仍可能被间接修改。

XML 配置无法自动产生不可变集合

Spring 的 XML 集合标签(<list> 等)不提供 immutable="true" 这类属性,也不支持调用 Collections.unmodifiableList() 这样的静态工厂方法。它只负责实例化和填充集合,不干预其运行时行为。

试图在 XML 中这样写是无效的:

  • <property name="items"><bean class="java.util.Collections" factory-method="unmodifiableList"><constructor-arg><list>...</list></constructor-arg></bean></property> —— 这不是标准用法,Spring 不识别此类嵌套工厂调用(除非自定义 FactoryBean

现代写法更倾向注解 + 构造注入 + 不可变语义

在 Spring Boot + Java 14+ 场景下,更自然的方式是:

  • @AllArgsConstructor 或显式构造函数接收集合参数
  • 字段声明为 final,并在构造中赋值并封装:this.roles = List.copyOf(roles);(Java 10+)或 Collections.unmodifiableList(...)
  • 配合 Lombok 的 @Builder 或 Record 类进一步强化不可变契约

例如:

public record Config(List<String> endpoints) {
  public Config {
    this.endpoints = List.copyOf(endpoints); // 不可变副本
  }
}

不复杂但容易忽略:不可变性不是配置出来的,而是设计出来的。Spring 注入的是“数据”,而“是否可变”取决于你如何持有和暴露它。

相关文章

精彩推荐