关于<context:property-placeholder>的一个有趣现象
转:http://stamen.iteye.com/blog/1926166
先来看下A和B两个模块
A模块
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模块
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容器就启动不了了:
到底出了啥问题
随便搜索了一下,还发现很多人遇到这个问题,这个就是来自stackoverflow的问题:
http://stackoverflow.com/questions/7940452/spring-application-context-not-able-to-load-property-placeholder-properties
可惜啊,好像都没有人给出正确的解决。
那究竟是什么问题呢?也想了很久哦....终于回想起来了(写书时读过Spring源码),原来是Spring容器采用反射扫描的发现机制,在探测到Spring容器中有一个org.springframework.beans.factory.config.PropertyPlaceholderConfigurer的Bean就会停止对剩余PropertyPlaceholderConfigurer的扫描(Spring 3.1已经使用PropertySourcesPlaceholderConfigurer替代PropertyPlaceholderConfigurer了)。
而<context:property-placeholder/>这个基于命名空间的配置,其实内部就是创建一个PropertyPlaceholderConfigurer Bean而已。换句话说,即Spring容器仅允许最多定义一个PropertyPlaceholderConfigurer(或<context:property-placeholder/>),其余的会被Spring忽略掉(其实Spring如果提供一个警告就好了)。
拿上来的例子来说,如果A和B模块是单独运行的,由于Spring容器都只有一个PropertyPlaceholderConfigurer,因此属性文件会被正常加载并替换掉。如果A和B两模块集成后运行,Spring容器中就有两个PropertyPlaceholderConfigurer Bean了,这时就看谁先谁后了, 先的保留,后的忽略!因此,只加载到了一个属性文件,因而造成无法正确进行属性替换的问题。
咋解决呢?
定位问题需要9999元钱,解决问题只需要1元钱
。
属性文件加载在统一的地方做,不要分模块加载即可。
A模块a.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_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>
B模块b.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_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>
集成:
- <?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为什么要这样呢?细想想是有道理的,一个项目或一个系统的配置应该放在一起,不宜分散。
这样才可以做到统一管控,否则到处都有配置,到底是加载哪个配置文件呢?有时你还会不小心让JAR中的Spring配置文件加载一个位于JAR中的属性文件,而外面有更改不了。如果Spring使用了这种机制,即使JAR包中的Spring配置文件使用<context:property-placeholder/>引用到JAR中的属性文件,只要你要外而的Spring配置文件中显示提供一个<context:property-placeholder/>指定另一个属性文件 ,就可以覆盖JAR中的默认配置了。
想了一想,Spring这样做是利大于弊的。
关于<context:property-placeholder>的一个有趣现象的更多相关文章
- Python有趣现象(不定时更新)
1.list中extend方法有趣现象 1.1 List+=Str 与 List.extend(Str) list1 = [11,2,45] str1 = 'Michael' list1.extend ...
- 关于Java中编码集的有趣现象和解释
这是在整理另一篇博客的时候发现的一个有趣的现象,是这样描述的:我们都知道Java默认使用的是UniCode编码集,我们也知道char类型占用两个字节.所以奇怪的现象又发生了(见代码): @Test p ...
- 【小贴士】关于transitionEnd/animate的一个有趣故事
前言 在很久之前,我们项目有一个动画功能,功能本身很简单,便是典型的右进左出,并且带动画功能 以当时来说,虽然很简单,但是受限于框架本身的难度,就直接使用了CSS3的方式完成了功能 当时主要使用tra ...
- 一个有趣的SQL Server 层级汇总数据问题
看SQL Server大V宋大侠的博客文章,发现了一个有趣的sql server层级汇总数据问题. 具体的问题如下: parent_id emp_id emp_nam ...
- 一个有趣的模拟光照的shader
一个有趣的模拟光照的shader(类似法线贴图) http://www.cnblogs.com/flytrace/p/3395911.html ----- 可否用于需UI中需要加灯的模型.
- 一个有趣的 SQL 查询(查询7天连续登陆)
一个有趣的 SQL 查询 一个朋友有这样一个SQL查询需求: 有一个登录表(tmp_test),包含用户ID(uid)和登录时间(login_time).表结构如下: . row ********** ...
- 另一个有趣的Captcha 网站
今天在一个网站注册时又发现了一个有趣的Captcha形式.给你一个翻转的图片,然后让你拽下面的slide bar让它回到正常的位置,很有趣.下面是提供这个Captcha的网站. minteye – s ...
- dubbo debug过程中一个有趣的问题
最近在debug dubbo代码过程中遇到的很有趣的问题 我们都知道dubbo ReferenceBean是消费者的spring bean包装,为了查一个consumer端的问题,在Reference ...
- 一个有趣的小例子,带你入门协程模块-asyncio
一个有趣的小例子,带你入门协程模块-asyncio 上篇文章写了关于yield from的用法,简单的了解异步模式,[https://www.cnblogs.com/c-x-a/p/10106031. ...
随机推荐
- log4jdbc打印完整SQL
一.log4jdbc简单介绍: log4jdbc是工作在jdbc层的一个日志框架,能够记录SQL及数据库连接执行信息. 一般的SQL日志会把占位符和参数值分开打印,log4jdbc则会记录数据库执行的 ...
- [CSS3] 学习笔记-选择器详解(三)
1.UI元素状态伪类选择器 在CSS3的选择器中,除了结构性伪类选择器外,还有一种UI元素伪类选择器.这些选择器的共同特征是:指定的样式只有当元素处于某种状态时才起作用,在默认状态下不起作用.在CSS ...
- C#进阶系列——使用Advanced Installer制作IIS安装包(二:配置安装包依赖项和自定义dll)
前言:上篇C#进阶系列——使用Advanced Installer制作IIS安装包(一:配置IIS和Web.config)介绍了下使用Advanced Installer配置IIS和Web.confi ...
- 成小胖学习ActiveMQ·基础篇
过了个春节,回到公司的成小胖变成了成大胖.但是你们千万别以为他那个大肚子里面装的都是肥肉,里面的墨水也多了不少嘞,毕竟成小胖利用春节的半个月时间专心学习并研究了 ActiveMQ,嘿嘿……这不,为了检 ...
- 解决npm install安装了太多架包的问题
比如我安装gulp时,会多出很多无用的包,如下图: 经过查询,原来是npm升级了导致的,在npm3.0以上的版本,包的依赖不再安装在每个架包的node_modules文件夹内,而是安装在顶层的node ...
- Vimium -为键盘而生
The hacker's browser. 作为一个Chrome的忠实使用者,从开发人员工具到谷歌的扩展程序(extensions)[插件],这些都在无形之中提高我们的工作效率. N年前的一天,看到了 ...
- plugman创建cordova插件
一.安装plumam npm install -g plugman 二.安装完之后,就可以创建plugin plugman create --name --plugin_id --plugin_ver ...
- 使用Jmeter3.1进行接口测试(包含需登录后测试的接口)
Jmeter版本为3.1,以下只针对此版本进行测试说明: 1.打开Jmeter3.1: 启动命令路径:apache-jmeter-3.1\bin\jmeter.bat 2.测试步骤: 1.测试计划-- ...
- web前端页面性能
前段性能的意义 对于访问一个网站,最花费时间的并不是后端应用程序处理以及数据库等消耗的时间,而是前端花费的时间(包括请求.网络传输.页面加载.渲染等).根据web优化的黄金法则:80%的最终用户响应时 ...
- C# .NET更智能的数据库操作的封装
前述: 对数据库操作的封装,相信网络上已经有一大堆,ORM框架,或者是.NET本身的EF,都很好的支持数据库操作.这篇文章是分享自己所思考的,对数据库操作的简单封装.我对于这篇文章,认为被浏览者所关注 ...