Spring源码学习--PropertyPlaceholderConfigurer类

2024-09-07 00:38

本文主要是介绍Spring源码学习--PropertyPlaceholderConfigurer类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章引用:

https://www.cnblogs.com/huqianliang/p/5673701.html
https://www.cnblogs.com/dream-to-pku/p/6367396.html

这里写图片描述

1 PropertyPlaceholderConfigurer是个bean工厂后置处理器的实现,也就是 BeanFactoryPostProcessor接口的一个实现。PropertyPlaceholderConfigurer可以将上下文(配置文 件)中的属性值放在另一个单独的标准java Properties文件中去。在XML文件中用${key}替换指定的properties文件中的值。这样的话,只需要对properties文件进 行修改,而不用对xml配置文件进行修改。

2 在Spring中,使用PropertyPlaceholderConfigurer可以在XML配置文件中加入外部属性文件,当然也可以指定外部文件的编码,如:

<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="location"><value>conf/sqlmap/jdbc.properties</value></property><property name="fileEncoding"><value>UTF-8</value></property>
</bean>

当然也可以引入多个属性文件,如:

<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="locations"><list><value>/WEB-INF/mail.properties</value>  <value>classpath: conf/sqlmap/jdbc.properties</value>//注意这两种value值的写法</list></property>
</bean>

3.譬如,jdbc.properties的内容为:

jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost/mysqldb?useUnicode=true&amp;characterEncoding=UTF-8&amp;zeroDateTimeBehavior=round;jdbc.username=rootjdbc.password=123456

4.那么在spring配置文件中,我们就可以这样写:

<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="locations"><list><value>classpath: conf/sqlmap/jdbc.properties </value></list></property>
</bean><bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><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>

5.这样,一个简单的数据源就设置完毕了。可以看出:PropertyPlaceholderConfigurer起的作用就是将占位符指向的数据库配置信息放在bean中定义的工具。

6.查看源代码,可以发现,locations属性定义在PropertyPlaceholderConfigurer的祖父类 PropertiesLoaderSupport中,而location只有 setter方法。类似于这样的配置,在spring的源程序中很常见的。

PropertyPlaceholderConfigurer如果在指定的Properties文件中找不到你想使用的属性,它还会在Java的System类属性中查找。

我们可以通过System.setProperty(key, value)或者java中通过-Dnamevalue来给Spring配置文件传递参数。




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

1 <context:property-placeholder location="userinfo.properties"/>

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

只需要在spring的配置文件里添加一句:<context:property-placeholder?location="classpath:jdbc.properties"/>?即可
这里location值为参数配置文件的位置,参数配置文件通常放在src目录下,而参数配置文件的格式跟java通用的参数配置文件相同,
即键值对的形式,例如:  #jdbc配置    
test.jdbc.driverClassName=com.mysql.jdbc.Driver  
test.jdbc.url=jdbc:mysql://localhost:3306/test  
test.jdbc.username=root  
test.jdbc.password=root  

这样一来就可以为spring配置的bean的属性设置值了,比如spring有一个jdbc数据源的类DriverManagerDataSource

在配置文件里这么定义bean:

<bean id="testDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="${test.jdbc.driverClassName}"/><property name="url" value="${test.jdbc.url}"/><property name="username" value="${test.jdbc.username}"/><property name="password" value="${test.jdbc.password}"/>
</bean>

这样修改起来也方便,也统一的这个规范。


另外需要注意的是,如果遇到下面着着这种问题:A模块和B模块都分别拥有自己的Spring XML配置,并分别拥有自己的配置文件:

A模块的Spring配置文件如下:

<?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:context="http://www.springframework.org/schema/context"  xmlns:p="http://www.springframework.org/schema/p"  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">  <context:property-placeholder location="classpath*:conf/conf_a.properties"/>  <bean class="com.xxx.aaa.Bean1"  p:driverClassName="${modulea.jdbc.driverClassName}"  p:url="${modulea.jdbc.url}"  p:username="${modulea.jdbc.username}"  p:password="${modulea.jdbc.password}"/>  
</beans>  

conf/conf_a.properties:

modulea.jdbc.driverClassName=com.mysql.jdbc.Driver  
modulea.jdbc.username=cartan  
modulea.jdbc.password=superman  
modulea.jdbc.url=jdbc:mysql://127.0.0.1:3306/modulea?useUnicode=true&characterEncoding=utf8  

B模块的Spring配置文件如下:

<?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:context="http://www.springframework.org/schema/context"    xmlns:p="http://www.springframework.org/schema/p"    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">    <context:property-placeholder location="classpath*:conf/conf_b.properties"/>    <bean class="com.xxx.bbb.Bean1"    p:driverClassName="${moduleb.jdbc.driverClassName}"    p:url="${moduleb.jdbc.url}"    p:username="${moduleb.jdbc.username}"    p:password="${moduleb.jdbc.password}"/>    
</beans>    

conf/conf_b.properties:

moduleb.jdbc.driverClassName=com.mysql.jdbc.Driver  
moduleb.jdbc.username=cartan  
moduleb.jdbc.password=superman  
moduleb.jdbc.url=jdbc:mysql://127.0.0.1:3306/modulea?useUnicode=true&characterEncoding=utf8  

单独运行A模块,或单独运行B模块都是正常的,但将A和B两个模块集成后运行,Spring容器就启动不了了:

Could not resolve placeholder ‘moduleb.jdbc.driverClassName’ in string value “${moduleb.jdbc.driverClassName}”

原因:Spring容器采用反射扫描的发现机制,在探测到Spring容器中有一个

org.springframework.beans.factory.config.PropertyPlaceholderConfigurer

的Bean就会停止对剩余PropertyPlaceholderConfigurer的扫描.


上述问题解决方案:

A和B模块去掉:

<context:property-placeholder location="classpath*:conf/conf_b.properties"/> 

然后重新写个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:context="http://www.springframework.org/schema/context"  xmlns:p="http://www.springframework.org/schema/p"  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">  <context:property-placeholder location="classpath*:conf/conf*.properties"/>  <import resource="a.xml"/>  <import resource="b.xml"/>  
</beans>  

这篇关于Spring源码学习--PropertyPlaceholderConfigurer类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1143571

相关文章

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

Java操作Word文档的全面指南

《Java操作Word文档的全面指南》在Java开发中,操作Word文档是常见的业务需求,广泛应用于合同生成、报表输出、通知发布、法律文书生成、病历模板填写等场景,本文将全面介绍Java操作Word文... 目录简介段落页头与页脚页码表格图片批注文本框目录图表简介Word编程最重要的类是org.apach

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

java如何解压zip压缩包

《java如何解压zip压缩包》:本文主要介绍java如何解压zip压缩包问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解压zip压缩包实例代码结果如下总结java解压zip压缩包坐在旁边的小伙伴问我怎么用 java 将服务器上的压缩文件解压出来,

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依