1、有时候需要从properties文件中加载配置,以前的方式是这样的:

  1. <bean id="jdbcProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  2. <property name="locations">
  3. <list>
  4. <value>classpath*:/spring/jdbc.properties</value>
  5. </list>
  6. </property>
  7. </bean>

spring推荐使用如下方式配置:

  1. <context:property-placeholder location="classpath:spring/jdbc.properties" />

以上两种方式,在bean定义中依然可以通过“${}”这种方式来去值:

  1. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  2. <property name="driverClassName" value="${jdbc.driverClassName}" />
  3. <property name="url" value="${jdbc.url}" />
  4. <property name="username" value="${jdbc.username}" />
  5. <property name="password" value="${jdbc.password}" />
  6. </bean>

注:<context:property-placeholder/>这个基于命名空间的配置,其实内部就是创建一个PropertyPlaceholderConfigurer Bean而已。

2、关于<context:property-placeholder>的一个有趣现象

先来看下A和B两个模块 ,A模块和B模块都分别拥有自己的Spring XML配置,并分别拥有自己的配置文件: 
A模块 ,A模块的Spring配置文件如下:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:p="http://www.springframework.org/schema/p"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
  8. <context:property-placeholder location="classpath*:conf/conf_a.properties"/>
  9. <bean class="com.xxx.aaa.Bean1"
  10. p:driverClassName="${modulea.jdbc.driverClassName}"
  11. p:url="${modulea.jdbc.url}"
  12. p:username="${modulea.jdbc.username}"
  13. p:password="${modulea.jdbc.password}"/>
  14. </beans>

其配置文件位于类路径conf/conf_a.properties中:

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

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

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:p="http://www.springframework.org/schema/p"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
  8. <context:property-placeholder location="classpath*:conf/conf_b.properties"/>
  9. <bean class="com.xxx.bbb.Bean1"
  10. p:driverClassName="${moduleb.jdbc.driverClassName}"
  11. p:url="${moduleb.jdbc.url}"
  12. p:username="${moduleb.jdbc.username}"
  13. p:password="${moduleb.jdbc.password}"/>
  14. </beans>

其配置文件位于类路径conf/conf_b.properties中:

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


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

原来是Spring容器采用反射扫描的发现机制,在探测到Spring容器中有一个org.springframework.beans.factory.config.PropertyPlaceholderConfigurer的Bean就会停止对剩余PropertyPlaceholderConfigurer的扫描(Spring 3.1已经使用PropertySourcesPlaceholderConfigurer替代PropertyPlaceholderConfigurer了)。 换句话说,即Spring容器仅允许最多定义一个PropertyPlaceholderConfigurer(或<context:property-placeholder/>),其余的会被Spring忽略掉(其实Spring如果提供一个警告就好了)。

拿上来的例子来说,如果A和B模块是单独运行的,由于Spring容器都只有一个PropertyPlaceholderConfigurer,因此属性文件会被正常加载并替换掉。如果A和B两模块集成后运行,Spring容器中就有两个PropertyPlaceholderConfigurer Bean了,这时就看谁先谁后了, 先的保留,后的忽略!因此,只加载到了一个属性文件,因而造成无法正确进行属性替换的问题。

解决:

A模块xml:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:p="http://www.springframework.org/schema/p"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
  8. <!--<context:property-placeholder location="classpath*:conf/conf_a.properties"/>-->
  9. <bean class="com.xxx.aaa.Bean1"
  10. p:driverClassName="${modulea.jdbc.driverClassName}"
  11. p:url="${modulea.jdbc.url}"
  12. p:username="${modulea.jdbc.username}"
  13. p:password="${modulea.jdbc.password}"/>
  14. </beans>

B模块b.xml:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:p="http://www.springframework.org/schema/p"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
  8. <!--<context:property-placeholder location="classpath*:conf/conf_b.properties"/>-->
  9. <bean class="com.xxx.bbb.Bean1"
  10. p:driverClassName="${moduleb.jdbc.driverClassName}"
  11. p:url="${moduleb.jdbc.url}"
  12. p:username="${moduleb.jdbc.username}"
  13. p:password="${moduleb.jdbc.password}"/>
  14. </beans>

集成:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:p="http://www.springframework.org/schema/p"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
  8. <context:property-placeholder location="classpath*:conf/conf*.properties"/>
  9. <import resource="a.xml"/>
  10. <import resource="b.xml"/>
  11. </beans>

Spring为什么要这样呢?细想想是有道理的,一个项目或一个系统的配置应该放在一起,不宜分散。 
这样才可以做到统一管控,否则到处都有配置,到底是加载哪个配置文件呢?有时你还会不小心让JAR中的Spring配置文件加载一个位于JAR中的属性文件,而外面有更改不了。如果Spring使用了这种机制,即使JAR包中的Spring配置文件使用<context:property-placeholder/>引用到JAR中的属性文件,只要你要外而的Spring配置文件中显示提供一个<context:property-placeholder/>指定另一个属性文件 ,就可以覆盖JAR中的默认配置了。

Spring配置:用context:property-placeholder替换PropertyPlaceholderConfigurer的更多相关文章

  1. Spring 配置 Annotation <context:annotation-config> 和 <context:component-scan>标签的诠释及区别

    Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别 <cont ...

  2. spring配置注解context:annotation-config和context:component-scan区别

    Spring 中在使用注解(Annotation)会涉及到< context:annotation-config> 和 < context:component-scan>配置, ...

  3. spring配置:context:property-placeholder 读取配置文件信息 在配置文件中使用el表达式填充值

    spring将properties文件读取后在配置文件中直接将对象的配置信息填充到bean中的变量里. 原本使用PropertyPlaceholderConfigurer类进行文件信息配置.Prope ...

  4. Spring配置中<context:annotation-config> VS <context:component-scan>

    Spring 中在使用注解(Annotation)会涉及到< context:annotation-config> 和 < context:component-scan>配置, ...

  5. Spring配置之context:annotation与、component-scan以及annotation-driven

    spring boot帮助我们隐藏了大量的细节,有些配置spring boot都是开启的,因此当我们查看遗留项目使用spring时候遇见问题一定细心排查 <!-- context:annotat ...

  6. spring错误:<context:property-placeholder>:Could not resolve placeholder XXX in string value XXX

    spring同时集成redis和mongodb时遇到多个资源文件加载的问题 这两天平台中集成redis和mongodb遇到一个问题 单独集成redis和单独集成mongodb时都可以正常启动程序,但是 ...

  7. [key]严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener(Spring配置异常)

    详细错误为: 严重: Exception sending context initialized event to listener instance of class org.springframe ...

  8. Spring 出现Could not resolve placeholder问题的解决方法

    项目开发中,使用@value注解获取不到配置文件里面的属性字段. 检查配置文件,在spring的配置文件中有配置读取,如下: <!-- 使用spring自带的占位符替换功能 --> < ...

  9. Spring(十):Spring配置Bean(三)Bean的作用域、使用外部属性文件

    Bean的作用域: 支持四种配置,分别是singleton,prototype,request,session. singleton 默认情况下在spring confinguration xml文件 ...

随机推荐

  1. 获取win10壁纸

    执行命令会将所有壁纸拷贝到桌面上的wallpaper文件夹内 bat xcopy %LOCALAPPDATA%\Packages\Microsoft.Windows.ContentDeliveryMa ...

  2. POJ 1330 Nearest Common Ancestors (dfs+ST在线算法)

    详细讲解见:https://blog.csdn.net/liangzhaoyang1/article/details/52549822 zz:https://www.cnblogs.com/kuang ...

  3. 第三章 四大组件之Activity(一)生命周期

    1.生命周期: onCreate()->onStart()->onResume()->onPause()->onStop()->onDestroy() 2.各种状况下Ac ...

  4. Apache 强制SSL访问

    RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R ...

  5. soot学习历程---(1)

    今天看了soot生成手册的部分内容,简单摘录一下 Scene 表示分析所处的完整环境,可以借此设置application class(用sootclass),主类(main),point-to和cal ...

  6. java常用类之BigDecimal

    BigDecimal 小数计算丢失精度问题 在计算机中,所有文件都是以二进制存储的,数字运算也是使用二进制进行计算的,因为计算机中不存在小数点,所以我们通常说的浮点数如float.double都是计算 ...

  7. JAVA知识点总结(六)(集合)

    第十九章 集合 一.数组弊端: 数组长度是固定的,无法继续添加元素. 二.什么是集合: Java提供一个集合类,它的长度是可以改变的,能储存任意的对象,长度随着元素的增加而增加. 三.集合和数组的区别 ...

  8. Dp test solution

    Dp test solution 按照难易程度排序题解: Problem B Problem Description Tarzan 现在想要知道,区间 [L,R] 内有多少数是优美的.我们定义一个数是 ...

  9. BZOJ 4033: [HAOI2015]树上染色题解

    BZOJ 4033: [HAOI2015]树上染色题解(树形dp) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327400 原题地址: BZOJ 403 ...

  10. Mysql中explain作用详解

    一.MYSQL的索引 1.索引(Index):帮助Mysql高效获取数据的一种数据结构.用于提高查找效率,可以比作字典.可以简单理解为排好序的快速查找的数据结构.2.索引的作用:便于查询和排序(所以添 ...