Spring-Mybatis MapperScannerConfigurer 取不到PropertyPlaceholderConfigurer里的值

      由于不想在xml里面重复繁琐的配置bean,所以使用MapperScannerConfigurer来扫描包自动生成实例交给spring管理。但是却发现取不到PropertyPlaceholderConfigurer里面的值导致初始化datasource失败。

    网上查阅发现只要修改SqlSessionFactoryBean的id不为sqlSessionFactory就行,说如果取名sqlSessionFactory就会触发dataSource提前初始化,但是为什么会提前,并没有相关解释。

     现状是datasource里面的配置没有替换掉所以初始化失败,所以我们要先看看配置是啥时候被替换的 。我们先看看spring初始化的过程(AbstractApplicationContext):

// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();

       再来看看这几个类的关系:

//MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor;

//PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessor
public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport;
public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfigurer;
public abstract class PropertyResourceConfigurer implements BeanFactoryPostProcessor;


public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor;

       那我们需要来看看invokeBeanFactoryPostProcessors(beanFactory),难道是先替换的属性值,再注册的BeanDefinition?

//other codes...
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
//other codes...
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

       显然不可能是顺序问题,那在看看报错信息,从autowiredByName出现问题。

org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:1244) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1194) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
	... 39 common frames omitted
protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        //propertyNames为bean可能需要注入的属性
        //在MapperScannerConfigurer中,有sqlSessionFactory,nameGenerator等
		for (String propertyName : propertyNames) {
       //重点来了,如果SqlSessionFactoryBean取名sqlSessionFactory,那么容器中将包含这个bean的定义
       //那么SqlSessionFactoryBean将会初始化,而如果SqlSessionFactoryBean里面的Datasource也取名datasource
       //那么SqlSessionFactoryBean初始化也会触发Datasource出事化,而此时还没走到配置值替换这个阶段
			if (containsBean(propertyName)) {
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				registerDependentBean(propertyName, beanName);
				
			else {
				
			}
		}
	}

         所以解决方案挺多的,把autowired by name去掉,SqlSessionFactoryBean不取名sqlSessionFactory,Datasource不取名datasource。

转载于:https://my.oschina.net/chener/blog/1617384

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值