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模块

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容器就启动不了了:

引用
Could not resolve placeholder 'moduleb.jdbc.driverClassName' in string value "${moduleb.jdbc.driverClassName}"

到底出了啥问题

随便搜索了一下,还发现很多人遇到这个问题,这个就是来自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:

  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这样做是利大于弊的。

参考链接:https://www.iteye.com/blog/stamen-1926166

Spring项目中Properties不能加载多个的问题的更多相关文章

  1. ContextLoaderListener和Spring MVC中的DispatcherServlet加载内容的区别【转】

    原文地址:https://blog.csdn.net/py_xin/article/details/52052627 ContextLoaderListener和DispatcherServlet都会 ...

  2. abp web.mvc项目中的菜单加载机制

    abp中的菜单加载机制 在abp中菜单的定义与我们传统写的框架不一样,它是在编写代码的时候配置,而我们一般写的通用权限管理系统中,是后期在后台界面中添加的.这一点有很大不同.abp关于菜单的定义及管理 ...

  3. ContextLoaderListener和Spring MVC中的DispatcherServlet加载内容的区别

    一:ContextLoaderListener加载内容 二:DispatcherServlt加载内容 ContextLoaderListener和DispatcherServlet都会在Web容器启动 ...

  4. 1.Spring项目启动时,加载相关初始化配置

    Spring项目启动时,会加载一些常用的配置: 1.加载spring上下文 SpringApplicationContextUtils.initApplicationContext(event.get ...

  5. 2、手把手教你Extjs5(二)项目中文件的加载过程

    上一节中用sencha工具自动创建了一个项目,并且可以在浏览器中查看.现在我们来看看js类加载过程.如下图所示: 1、首先:浏览器中输入 localhost:1841 ,调用 index.html; ...

  6. 关于web项目中静态资源加载不了的一些解决思路

    问题的产生: <!--springMVC前端控制器加载--> <servlet> <servlet-name>springmvc</servlet-name& ...

  7. web项目中配置文件的加载顺序

    当一个项目启动时,首先是web.xml: 这里面的配置: 为什么要在web.xml中配置struts的过滤器? 因为一个web项目运行的时需要加载的,或者默认的部分配置都会在web.xml中配置,中间 ...

  8. Vue编写的页面部署到springboot网站项目中出现页面加载不全问题

    问题描述: 在用Vue脚手架 编写出一个页面之后, 部署到后台项目中, 因为做的是一个页面 按理来说 怎么都能够在服务器上运行 , 我也在自己的node环境测试 , 在同学的springboot上运行 ...

  9. SpringMVC项目中启动自加载Listener

    package com.kuman.cartoon.listener; import java.util.List; import org.springframework.beans.factory. ...

随机推荐

  1. Django:RestFramework之-------解析器

    7.解析器 依靠Content-Type对用户的请求体中的数据进行解析. 7.1django中的解析器 前戏:django中的request.POST/request.body request.POS ...

  2. 纯css无js实现点击事件

    <input id="A" type="checkbox"><label for="A"> <span cla ...

  3. FastJson实现复杂对象序列化与反序列化

    原文:http://blog.csdn.net/xqhadoop/article/details/62217954 一.认识FastJson 1.优势 fastjson是目前java语言中最快的jso ...

  4. APP安全测试

    app 常见风险 一. clinet端 1.反编译 2.签名破解 3.调试 4.导出组件 5.拒绝服务 6.输入记录 二.传输 1.信息泄露,未使用加密服务(ssl) 2.篡改 三.服务端 1.SQL ...

  5. profile name is not valid,The EXECUTE permission was denied on the object 'sp_send_dbmail', database 'msdb', schema 'dbo'.

    使用不是sysadmin权限的账号执行存储发邮件,报异常profile name is not valid, EXEC msdb.dbo.sp_send_dbmail @profile_name = ...

  6. linux设备驱动程序--在用户空间注册文件接口

    linux字符设备驱动程序--创建设备节点 基于4.14内核,运行在beagleBone green 在上一讲中,我们写了第一个linux设备驱动程序--hello_world,在驱动程序中,我们什么 ...

  7. (九)Kubernetes 存储卷

    Kubernetes存储卷概述 Pod本身具有生命周期,这就带了一系列的问题,第一,当一个容器损坏之后,kubelet会重启这个容器,但是文件会丢失-这个容器会是一个全新的状态:第二,当很多容器在同一 ...

  8. XSS简单练习

    xss平台: https://xss.haozi.me题解: https://blog.csdn.net/AlexYoung28/article/details/82315538 对在xss.haoz ...

  9. php原型模式(prototype pattern)

    练练练,计划上午练完创建型设计模式. <?php /* The prototype pattern replicates other objects by use of cloning. Wha ...

  10. jmeter中设置线程数与设置集合点的区别

    1.设置线程数: 表示10秒内启动50个线程, 运行结果如下:10秒内启动了50个线程 2.设置集合点: Number of Simulated Users to Group by:50,表示集合50 ...