Spring-Mybatis MapperScannerConfigurer 取不到PropertyPlaceholderConfigurer里的值

原创
2018/02/02 14:40
阅读数 791

      由于不想在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。

展开阅读全文
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部