Spring util 命名空间详解

Spring util 命名空间详解

一、util 命名空间是什么?

util 命名空间是 Spring 提供的一个 XML 扩展命名空间,专门用于定义集合类型的 Bean。它解决了标准 XML 配置中集合无法独立定义、无法被多个 Bean 复用的问题。

在没有 util 命名空间时,集合只能内联在某个 Bean 的 <property> 中:

xml 复制代码
<bean id="userService" class="com.example.UserService">
    <property name="servers">
        <list>
            <value>server1</value>
            <value>server2</value>
        </list>
    </property>
</bean>

这个 List 只属于 userService,其他 Bean 无法引用它。如果多个 Bean 需要同一个集合,只能重复配置。

util 命名空间允许把集合定义成独立的 Bean,赋予 id,然后通过 ref 注入到任意 Bean 中。

xml 复制代码
<util:list id="serverList">
    <value>server1</value>
    <value>server2</value>
</util:list>

<bean id="userService" class="com.example.UserService">
    <property name="servers" ref="serverList"/>
</bean>

<bean id="orderService" class="com.example.OrderService">
    <property name="servers" ref="serverList"/>
</bean>

serverList 成为一个独立的 Bean,可以被多个 Bean 共享。

二、引入 util 命名空间

在 XML 根元素中声明:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- util 标签在这里使用 -->

</beans>

关键是 xmlns:util 和 spring-util.xsd 两行。没有它们,<util:list> 等标签不会被解析。

三、常用标签详解

3.1 <util:list> 定义 List Bean

xml 复制代码
<util:list id="serverList" list-class="java.util.ArrayList">
    <value>server1</value>
    <value>server2</value>
    <value>server3</value>
</util:list>

list-class 可选,默认是 ArrayList。如果需要 LinkedList,可以指定:

xml 复制代码
<util:list id="serverList" list-class="java.util.LinkedList">

List 中可以放简单值、Bean 引用、嵌套集合。

xml 复制代码
<util:list id="mixedList">
    <value>text</value>
    <ref bean="userDao"/>
    <bean class="com.example.User"/>
</util:list>

3.2 <util:set> 定义 Set Bean

xml 复制代码
<util:set id="serverSet" set-class="java.util.LinkedHashSet">
    <value>server1</value>
    <value>server2</value>
    <value>server1</value>  <!-- 自动去重 -->
</util:set>

set-class 可选,默认是 LinkedHashSet。Set 会自动去重,元素顺序取决于实现类。

3.3 <util:map> 定义 Map Bean

xml 复制代码
<util:map id="configMap" map-class="java.util.LinkedHashMap">
    <entry key="timeout" value="30"/>
    <entry key="retry" value="3"/>
    <entry key="debug" value="true"/>
</util:map>

map-class 可选,默认是 LinkedHashMap。entry 的 key 和 value 可以是简单值、Bean 引用、嵌套对象。

xml 复制代码
<util:map id="beanMap">
    <entry key="primary" value-ref="primaryDataSource"/>
    <entry key="secondary" value-ref="secondaryDataSource"/>
</util:map>

3.4 <util:properties> 定义 Properties Bean

方式一:从外部文件加载

xml 复制代码
<util:properties id="dbProps" location="classpath:db.properties"/>

方式二:内联定义

xml 复制代码
<util:properties id="appProps">
    <prop key="app.name">myapp</prop>
    <prop key="app.timeout">30</prop>
</util:properties>

<util:properties> 返回的是 java.util.Properties 对象,键和值都是 String。

3.5 <util:constant> 引用静态常量

xml 复制代码
<util:constant id="maxValue" static-field="java.lang.Integer.MAX_VALUE"/>
<util:constant id="charset" static-field="java.nio.charset.StandardCharsets.UTF_8"/>

static-field 写全限定类名加字段名。常用于把某个静态常量注册为 Bean。

3.6 <util:property-path> 引用其他 Bean 的属性

xml 复制代码
<bean id="user" class="com.example.User">
    <property name="name" value="张三"/>
</bean>

<util:property-path id="userName" path="user.name"/>

userName 成为一个 Bean,值是 user 的 name 属性。常用于把某个 Bean 的属性暴露为独立的 Bean。

四、与标准集合标签的区别

对比维度 util 命名空间 标准 <list>、<map>
是否独立 Bean 是,有 id 否,内联在属性中
是否可复用 可被多个 Bean 引用 只属于当前 Bean
是否可单独获取 可以,getBean("id") 不可以
定义位置 直接放在 <beans> 下 嵌套在 <property> 或 <constructor-arg> 中
适用场景 多个 Bean 共享集合 单个 Bean 的私有集合

五、与 p 命名空间配合

p 命名空间不能直接定义集合,但可以引用 util 定义的集合 Bean。

xml 复制代码
<util:list id="serverList">
    <value>server1</value>
    <value>server2</value>
</util:list>

<bean id="userService" class="com.example.UserService"
      p:servers-ref="serverList"
      p:appName="myapp"/>

这种组合在 XML 配置时代很常见:util 负责定义集合,p 负责注入。

六、底层原理

util 命名空间的解析由 UtilNamespaceHandler 完成,它注册了以下 BeanDefinitionParser:

标签 解析器
<util:list> ListBeanDefinitionParser
<util:set> SetBeanDefinitionParser
<util:map> MapBeanDefinitionParser
<util:properties> PropertiesBeanDefinitionParser
<util:constant> ConstantBeanDefinitionParser
<util:property-path> PropertyPathBeanDefinitionParser

以 <util:list> 为例,解析器会创建一个 ListFactoryBean 的 BeanDefinition,把 list-class、value、ref 等配置转换为 ListFactoryBean 的属性。容器实例化时,ListFactoryBean 的 getObject() 返回实际的 List 对象。

所以 util 定义的集合本质上是工厂 Bean 生产的产品,而不是直接注册的集合对象。

七、完整示例

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util.xsd">

    <util:list id="serverList" list-class="java.util.ArrayList">
        <value>server1.example.com</value>
        <value>server2.example.com</value>
        <value>server3.example.com</value>
    </util:list>

    <util:set id="roleSet">
        <value>admin</value>
        <value>user</value>
        <value>admin</value>
    </util:set>

    <util:map id="configMap">
        <entry key="timeout" value="30"/>
        <entry key="retry" value="3"/>
    </util:map>

    <util:properties id="appProps">
        <prop key="app.name">myapp</prop>
        <prop key="app.version">1.0</prop>
    </util:properties>

    <bean id="userService" class="com.example.UserService"
          p:servers-ref="serverList"
          p:roles-ref="roleSet"
          p:configs-ref="configMap"
          p:props-ref="appProps"/>

</beans>

Java 类:

java 复制代码
public class UserService {
    private List<String> servers;
    private Set<String> roles;
    private Map<String, String> configs;
    private Properties props;
    
    // setter 方法
    public void setServers(List<String> servers) { this.servers = servers; }
    public void setRoles(Set<String> roles) { this.roles = roles; }
    public void setConfigs(Map<String, String> configs) { this.configs = configs; }
    public void setProps(Properties props) { this.props = props; }
}

八、注意事项

1. 需要声明 util 命名空间和 schemaLocation

缺少 xmlns:util 或 spring-util.xsd,标签不会被解析。

2. id 必须唯一

util 定义的集合是独立 Bean,id 不能与其他 Bean 重复。

3. 集合元素类型

<value> 默认是 String,Spring 会尝试类型转换。如果集合是 List<Integer>,Spring 会自动把 "30" 转成 30。

4. <util:properties> 的 location

加载外部文件时,路径要写对:classpath:db.properties 或 file:/opt/config/db.properties。

5. 不支持数组

util 命名空间没有 <util:array>。需要数组时,用 <util:list> 定义 List,注入到数组类型的属性时 Spring 会自动转换。

6. 现代项目中使用减少

Spring Boot 以 Java 配置和注解为主,util 命名空间主要出现在老项目和传统 XML 配置中。理解它有助于维护旧代码。

九、总结

维度 核心要点
作用 定义独立、可复用的集合 Bean
引入 xmlns:util + spring-util.xsd
常用标签 <util:list>、<util:set>、<util:map>、<util:properties>、<util:constant>、<util:property-path>
与标准集合区别 util 定义的集合是独立 Bean,可被多个 Bean 引用
与 p 命名空间配合 util 定义集合,p 负责注入
底层 UtilNamespaceHandler + 各标签的 BeanDefinitionParser,本质是工厂 Bean
适用场景 多个 Bean 共享集合、需要单独获取集合 Bean、加载 Properties 文件
注意事项 需要命名空间声明、id 唯一、不支持数组、现代项目使用减少

util 命名空间是 Spring XML 配置时代管理集合 Bean 的标准工具。它让集合从"某个 Bean 的私有属性"变成"容器中可共享的资源",在需要多个 Bean 共用同一组配置或集合时非常有用。虽然在新项目中已经很少直接使用,但阅读和维护老项目时,掌握 util 命名空间能帮你快速理解配置结构。

相关推荐
Sarvartha6 小时前
final 关键字
java·开发语言
2601_952047796 小时前
单一策略深度教程:用轻易云把集成任务的报错实时推送到钉钉机器人
java·机器人·钉钉
Joy T6 小时前
Spring AI 项目中的 pom.xml、application.yml 与 Nacos:从依赖管理到运行配置
spring·nacos·pom.xml·profile·参数配置·application.yml
数据狐(Datafox)7 小时前
淘宝图片搜索 API 落地实战:基于以图搜货搭建跨境电商选品系统
java·大数据·微服务
刚子编程8 小时前
我用 ASP.NET Core 做了个水稻病虫害检查系统
后端·asp.net
谢亮_vipxieliang9 小时前
用 PHP 构建轻量级 REST API:从路由到鉴权的完整实践
开发语言·后端·php
Escalating_xu9 小时前
【C 语言】数据在内存中的存储:补码、大小端、整型陷阱与 IEEE 754 全解析
java·c语言·网络
灯澜忆梦9 小时前
【面向对象编程C++】| 基础语法
java·c++·算法