Spring源码学习|MapperScannerConfigurer导致PlaceHolder的替换变量报错

前提 1.开启了byName自动注入
2.定义了PropertySourcesPlaceholderConfigurer,去解析配置。
3.含有id="sqlSessionFactory"的SqlSessionFactory
4.定义了MapperScannerConfigurer,在其属性sqlSessionFactory中的dataSource属性中使用了${username}${password}等。
原因

  1. MapperScannerConfigurer 是一个BeanDefinitionRegistryPostProcessor,它是BeanFactoryPostProcessor的实现类。
  2. 【Spring源码学习|MapperScannerConfigurer导致PlaceHolder的替换变量报错】PropertySourcesPlaceholderConfigurer是一个BeanFactoryPostProcessor的实现类。
  3. MapperScannerConfigurer 在 PropertySourcesPlaceholderConfigurer 之前被实例化。
    3.1. 这是因为它们会在Spring的refresh->invokeBeanFactoryPostProcessors(beanFactory)被调用。 而顺序是 先注册BeanDefinitionFactoryProcessor,再注册BeanFactoryPostProcessor
  4. MapperScannerConfigurer优先实例化的时候,开启了default-autowire="byName"会连同属性sqlSessionFactory一起初始化,并造成dataSource初始化, 那么${username}被提前设置到dataSource中的username属性中,但此时PropertySourcesPlaceholderConfigurer还未生成实例,更没有替换${username},导致错误!
    4.1 开启default-autowire="byName"自动注入后,会解析出需要"sqlSessionFactory"依赖,并提前初始化。
解决 由于无法改变MapperScannerConfigurer与PropertySourcesPlaceholderConfigurer的getBean初始化顺序。
那么避免sqlSessionFactory的属性提前初始化。
1.去掉default-autowire="byName"
2.改变sqlSessionFactory的id。(未验证) (TODO)
常见报错配置

参考
https://my.oschina.net/u/161336/blog/1830816

    推荐阅读