Spring读取配置文件无法解析问题

问题背景:

  • 这个问题排查了有2-3天,尝试了各种组合配置没有解决。最后还是查资料看别人的解决经验解决了。

问题现象:

  • 一个17年的老项目继续开发,其中是spring+mybatis+ibatis组合,基于一个更早12年的ibatis老项目开发的(开源otter)。把spring的配置datasource的xml文件中datasrouce的driver,url,username,password改成application.properties中使用spring的PropertyPlaceholderConfigurer来进行配置文件读取值替换。但是怎么配都提示变量无法解析。查了很多材料,都是说PropertyPlaceholderConfigurer的用法和spring怎么配外部配置文件的。没有关键信息、
  • 如果不用配置文件,直接写死是没问题的。使用xml中的properties属性也不行。
  • 错误如下图:
  • 怀疑与bean的初始化顺序有关,也就是datasource的bean初始化的时候还没有进行配置文件解析,PropertyPlaceholderConfigurer还没生效。

主要探索过程:

  • 首先想到占位符的原理,参考该文章:
    • 深入Spring Boot:那些注入不了的Spring占位符(${}表达式)
    • https://blog.csdn.net/hengyunabc/article/details/75453307
    • 与该文章现象一致,并提示:结合上面的Spring的生命周期,如果Bean的创建和使用在PropertySourcesPlaceholderConfigurer之前,那么就有可能出现占位符没有被处理的情况。并提出:Mybatis 的 MapperScannerConfigurer引起的占位符没有处理,查出该类导致了datasource的bean提前初始化,在配置还没解析前。所以报错。
    • 大概原因就应该是这个。
  • 继续探索:
    • 从配置文件PropertySourcesPlaceholderConfigurer何时生效继续看,找出另一个文章:关于dubbo 占位符无法解析问题
    • https://blog.csdn.net/su20145104009/article/details/105160565
    • 该文提出思路:此时,只有一种想法,难道该 bean 的初始化早于 PropertySourcesPlaceholderConfigurer 的替换?也就是说,RegistryConfig 被提前初始化了
    • 该文提出解决方法:也关注到了:注册MapperScannerConfigurer的bean被提前初始化的问题
    • 但是改了其中的参数,还是没解决我的问题。但是排查问题过程更清晰。
  • 继续探索:
    • 在bing搜索:PropertyPlaceholderConfigurer无法注入,偶然得到一个文章:
    • PropertyPlaceholderConfigurer模式从properties加载数据源参数失败的解决方案
    • https://www.iteye.com/blog/yjy110-1882876
    • 报错类似,同时也将问题关注到了:一开始怀疑是spring版本问题,就搜索了一下“spring3 PropertyPlaceholderConfigurer”,结果发现还真有类似的提问,只不过比我问的更准确,一下就把问题定位到了问题的根源-------mybatis下的MapperScannerConfigurer扫描模式造成了bean的加载顺序改变从而使得PropertyPlaceholderConfigurer无法正常加载。
      改用sqlSessionFactoryBeanName注入就没有问题(不要使用sqlSessionFactory属性注入,使用sqlSessionFactoryBeanName注入),因为这时不会立即初始化sqlSessionFactory,传入的只是名字,非bean,所以不会引发提前初始化问题。。
    • 该文给出的MapperScannerConfigurer的sqlSessionFactory注入方式也没解决问题,不过已经可以确认问题就是这个。
    • 文中给出1个链接:https://www.oschina.net/question/188964_32305?sort=default&p=3
    • spring3.0.6 使用context:property-placeholder载不进属性
    • 该问题下面好多人遇到了类似问题,有人提出关键点:
    • 两种解决办法:
1. <!-- mybatis文件配置,扫描所有mapper文件 -->
<!-- configLocation为mybatis属性 mapperLocations为所有mapper -->
<bean id="mb-sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" 
  p:dataSource-ref="dataSource" p:configLocation="classpath:web/sqlmap/mybatis-config.xml" 
  p:mapperLocations="classpath:web/sqlmap/mapper/*.xml" />
  <!-- spring与mybatis整合配置,扫描所有dao -->
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"p:basePackage="com.jiezhibar.candy.web.dao" 
     p:sqlSessionFactoryBeanName="mb-sqlSessionFactory" />
  即:sqlSessionFactoryBeanName的值写成非sqlSessionFactory

2、xml 头部将 default-autowire="byName"去掉
原文地址:https://www.cnblogs.com/drawnkid/p/15770953.html