关于mybatis集成spring时,dataSource设置propertyPlaceholder的问题
2015-03-16 11:10
447 查看
PS:之前使用的是mybatis的1.0.2版,发现最新的版本1.2.2已经修改了这个问题
今天在开发过程中发现mybatis和spring集成的时候。在mybatis写了mapper时,用spring配置的dataSource数据库连接池中使用${xxx}形式会报错误,从错误的提示中看出是数据库连接池中${xxx}并没有替换。
查询源代码发现mybatis与spring集成时,设置的xml的mapper扫描使用的是spring的BeanDefinitionRegistryPostProcessor
而mapper中生成对应的beanDefinition的方法是在postProcessBeanDefinitionRegistry中扫描所有的mybatis的sql配置文件
而spring中的PropertyPlaceholder是使用的是spring中的BeanFactoryPostProcessor
spring是启动容器时,执行的顺序是先执行所有的BeanDefinitionRegistryPostProcessor,再执行BeanFactoryPostProcessor。所以这里在执行扫码mybatis的Mapper时,引用的数据源dataSource还没有解析替换成相当的properties中的值
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (this.processPropertyPlaceHolders) { processPropertyPlaceHolders(); } ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); scanner.setAddToConfig(this.addToConfig); scanner.setAnnotationClass(this.annotationClass); scanner.setMarkerInterface(this.markerInterface); scanner.setSqlSessionFactory(this.sqlSessionFactory); scanner.setSqlSessionTemplate(this.sqlSessionTemplate); scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName); scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName); scanner.setResourceLoader(this.applicationContext); scanner.setBeanNameGenerator(this.nameGenerator); scanner.registerFilters(); scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); }
今天在开发过程中发现mybatis和spring集成的时候。在mybatis写了mapper时,用spring配置的dataSource数据库连接池中使用${xxx}形式会报错误,从错误的提示中看出是数据库连接池中${xxx}并没有替换。
查询源代码发现mybatis与spring集成时,设置的xml的mapper扫描使用的是spring的BeanDefinitionRegistryPostProcessor
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com."/> <property name="sqlSessionFactory" ref="sqlSessionFactoryCService"></property> </bean>
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
而mapper中生成对应的beanDefinition的方法是在postProcessBeanDefinitionRegistry中扫描所有的mybatis的sql配置文件
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { Scanner scanner = new Scanner(beanDefinitionRegistry); scanner.setResourceLoader(this.applicationContext); scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); }
而spring中的PropertyPlaceholder是使用的是spring中的BeanFactoryPostProcessor
public abstract class PropertyResourceConfigurer extends PropertiesLoaderSupport implements BeanFactoryPostProcessor, PriorityOrdered
spring是启动容器时,执行的顺序是先执行所有的BeanDefinitionRegistryPostProcessor,再执行BeanFactoryPostProcessor。所以这里在执行扫码mybatis的Mapper时,引用的数据源dataSource还没有解析替换成相当的properties中的值
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<String>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) { //此时先执行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry() if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryPostProcessor.postProcessBeanDefinitionRegistry(registry); registryPostProcessors.add(registryPostProcessor); } else { regularPostProcessors.add(postProcessor); } } Map<String, BeanDefinitionRegistryPostProcessor> beanMap = beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false); List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans = new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values()); OrderComparator.sort(registryPostProcessorBeans); for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) { postProcessor.postProcessBeanDefinitionRegistry(registry); } invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); processedBeans.addAll(beanMap.keySet()); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); List<String> orderedPostProcessorNames = new ArrayList<String>(); List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. OrderComparator.sort(priorityOrderedPostProcessors); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class)); } OrderComparator.sort(orderedPostProcessors); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); }
相关文章推荐
- spring boot集成mybatis,启动报无法创建dataSource问题
- 关于spring整合mybatis的扫描器的配置问题
- 关于Mybatis与Spring整合之后SqlSession与mapper对象之间数量的问题。
- 关于IDEA工具在springboot整合mybatis中出现的Invalid bound statement (not found)问题
- 关于springboot+websocket+mybatis的问题
- 关于spring boot整合mybatis使用oracle数据库出现could not load:oracle.jdbc.driver.OracleDriver问题的终极解决方案
- [小技巧]关于spring boot 整合mybatis-plus: value为null时不返回的问题。
- Maven项目中,关于Spring Boot 整合MyBatis时,Service层无法找到mapper接口的问题解决
- spring和mybatis集成出现的问题
- struts2与spring集成时,关于Action类中成员bean自动注入的问题
- 关于Spring集成JSF是的问题
- mybatis-spring集成:配置多数据库源中遇到的问题--MapperScannerConfigurer配置
- struts2与spring集成时,关于class属性及成员bean自动注入的问题
- SPRING 和 MYBATIS集成的WARN问题
- Spring集成mybatis时配置propertyPlaceholder加载dataSource失效
- struts2与spring集成时,关于Action类中成员bean自动注入的问题
- SM59配置RFC&关于SAP与其它系统集成SM59设置目标系统的问题
- 关于spring和mybatis集成后如何进行批处理总结
- 关于maven+springMVC+mybatis搭建的web项目问题
- struts2与spring集成时,关于Action类中成员bean自动注入的问题