PropertyPlaceholderConfigurer 类解析

本文将介绍 Spring 中的 PropertyPlaceholderConfigurer 类,以及自定义实现属性文件解析器。

在 Spring 中,使用 PropertyPlaceholderConfigurer 可以在 XML 配置文件中加入外部属性文件,当然也可以指定外部文件的编码。PropertyPlaceholderConfigurer 可以将上下文(配置文 件)中的属性值放在另一个单独的标准 java Properties 文件中。在 XML 文件中用 ${key} 替换指定的 properties 文件中的值。这样的话,只需要对 properties 文件进行修改,而不用对 XML 配置文件进行修改。

PropertyPlaceholderConfigurer 是个 bean 工厂后置处理器的实现,也就是 BeanFactoryPostProcessor 接口的一个实现。源码实现如下:

PropertyPlaceholderConfigurer 类解析

使用PropertyPlaceholderConfigurer类

(1)编写 db.properties 属性文件

jdbc.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
jdbc.username=root
jdbc.password=aaaaaa

(2)在 xml 中引入外部属性文件,即 .properties 文件。如果引单个文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="https://www.springframework.org/schema/context"
       xsi:schemaLocation="https://www.springframework.org/schema/beans 
         https://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
         https://www.springframework.org/schema/context
         https://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:component-scan base-package="com.hxstrive"/>
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:db.properties</value>
            </list>
        </property>
    </bean>
</beans>

如果引多个文件,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="https://www.springframework.org/schema/context"
       xsi:schemaLocation="https://www.springframework.org/schema/beans 
         https://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
         https://www.springframework.org/schema/context
         https://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:component-scan base-package="com.hxstrive"/>
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:db.properties</value>
                <value>classpath:db2.properties</value>
                <value>classpath:db3.properties</value>
            </list>
        </property>
    </bean>
</beans>

引入外部文件后,就可以在 xml 中用 ${key} 替换指定的 properties 文件中的值,通常项目中都会将 jdbc 的配置放在 properties 文件中。如下:

<!-- 配置dbcp数据源 -->
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

在启动容器时,初始化 bean 时,${key} 就会替换成 properties 文件中的值。

使用<context:property-placeholder/>

为了简化 PropertyPlaceholderConfigurer 的使用,Spring提供了<context:property-placeholder/>元素,启用它后,开发者便不用配置 PropertyPlaceholderConfigurer 对象了。

(1)编写 db.properties 属性文件

jdbc.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
jdbc.username=root
jdbc.password=aaaaaa

(2)使用 <context:property-placeholder/> 配置属性文件的位置,如下:

<!-- 数据库配置文件位置 -->
<context:property-placeholder location="classpath:db.properties" />

PropertyPlaceholderConfigurer 内置的功能非常丰富,如果它未找到 ${xxx} 中定义的 xxx 键,它还会去 JVM 系统属性(System.getProperty())和环境变量(System.getenv())中寻找。通过启用 systemPropertiesMode 和searchSystemEnvironment 属性,开发者能够控制这一行为。<context:property-placeholder/> 大大的方便了我们数据库的配置,这样就可以为 spring 配置的 bean 的属性设置值了。如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="https://www.springframework.org/schema/context"
       xsi:schemaLocation="https://www.springframework.org/schema/beans 
         https://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
         https://www.springframework.org/schema/context
         https://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:component-scan base-package="com.hxstrive"/>
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="searchSystemEnvironment" value="true" />
        <property name="systemPropertiesMode" value="1"/>
        <property name="locations">
            <list>
                <value>classpath:db.properties</value>
            </list>
        </property>
    </bean>
</beans>

(3)配置bean的属性

<!-- 配置dbcp数据源 -->
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

注:spring 容器中最多只能定义一个 <context:property-placeholder/>,否则会报错:Could not resolve placeholder XXX。如果我们想引入多个属性文件怎么办呢?可以使用通配符:<context:property-placeholder location="classpath*:conf*.properties"/>

自定义 PropertyPlaceholderConfigurer

自定义 PropertyPlaceholderConfigurer 非常简单,需要继承 PropertyPlaceholderConfigurer 类,并且重写 processProperties() 方法。例如:

package com.huangx.spring4.rewrite;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 自定义 PropertyPlaceholderConfigurer
 * @author administrator
 */
public class MyPropertyPlaceholder extends PropertyPlaceholderConfigurer {
    private static Map<String,String> propertyMap;

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
        super.processProperties(beanFactoryToProcess, props);
        propertyMap = new HashMap<String, String>();
        for (Object key : props.keySet()) {
            String keyStr = key.toString();
            String value = props.getProperty(keyStr);
            propertyMap.put(keyStr, value);
            System.out.println(keyStr + "=" + value);
        }
    }

    // 自定义一个方法,即根据 key拿属性值,方便 java 代码中取属性值
    public static String getProperty(String name) {
        return propertyMap.get(name);
    }

}

在创建 bean 时就会调用 processProperties() 方法,属性文件中设置的键值对已经全部放到了参数 Properties 中,怎么使用这些值,需要根据实际业务需要。

接下来,我们就可以在 XML 中配置使用我们自定义的 PropertyPlaceholderConfigurer 类。如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="https://www.springframework.org/schema/context"
       xsi:schemaLocation="https://www.springframework.org/schema/beans 
         https://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
         https://www.springframework.org/schema/context
         https://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:component-scan base-package="com.huangx.spring4"/>
    <bean class="com.huangx.spring4.rewrite.MyPropertyPlaceholder">
        <property name="searchSystemEnvironment" value="true" />
        <property name="systemPropertiesMode" value="1"/>
        <property name="locations">
            <list>
                <value>classpath:props/db.properties</value>
            </list>
        </property>
    </bean>
</beans>
尺有所短;寸有所长。物有所不足;智有所不明。——屈原《卜居》
1 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号