MapperScannerConfigurer与<context:property-placeholder>加载顺序导致异常解决办法
来源:互联网 发布:天刀唐门男捏脸数据 编辑:程序博客网 时间:2024/05/23 19:20
在使用Spring和MyBaits整合时,使用c3p0数据源,将数据源配置信息写在属性文件中,然后使用<context:property-placeholder>引入配置文件,但是同时使用MapperScannerConfigurer类自动配置Mapper,启动时抛出
java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41) at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) at org.junit.runners.ParentRunner.run(ParentRunner.java:220) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean
with name 'mapperScannerConfigurer' defined in class path resource [spring.xml]:
Cannot resolve reference to bean 'sqlSessionFactory' while setting bean property 'sqlSessionFactory';
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sqlSessionFactory' defined in class path resource [spring.xml]:
Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource';
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dataSource' defined in class path resource [spring.xml]:
Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException:
Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'initialPoolSize';
nested exception is java.lang.NumberFormatException: For input string: "${pool.c3p0.initialPoolSize}" at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:400) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:612) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:446) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1) at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228) at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124) at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148) ... 24 moreCaused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [spring.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [spring.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'initialPoolSize'; nested exception is java.lang.NumberFormatException: For input string: "${pool.c3p0.initialPoolSize}" at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322) ... 41 moreCaused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [spring.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'initialPoolSize'; nested exception is java.lang.NumberFormatException: For input string: "${pool.c3p0.initialPoolSize}" at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322) ... 51 moreCaused by: org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.lang.String' to required type 'int' for property 'initialPoolSize'; nested exception is java.lang.NumberFormatException: For input string: "${pool.c3p0.initialPoolSize}" at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:490) at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:516) at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:510) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1406) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1365) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) ... 57 moreCaused by: java.lang.NumberFormatException: For input string: "${pool.c3p0.initialPoolSize}" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer.java:447) at java.lang.Integer.valueOf(Integer.java:553) at org.springframework.util.NumberUtils.parseNumber(NumberUtils.java:155) at org.springframework.beans.propertyeditors.CustomNumberEditor.setAsText(CustomNumberEditor.java:115) at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:431) at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:403) at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:163) at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:470) ... 63 more
我的配置:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="com.ssi.bus" />
<!-- 引入资源文件 --> <context:property-placeholder location="classpath:dbconfig.properties"/>
<!-- c3p0数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClass}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="initialPoolSize" value="${pool.c3p0.initialPoolSize}" /> <property name="minPoolSize" value="${pool.c3p0.minPoolSize}" /> <property name="maxPoolSize" value="${pool.c3p0.maxPoolSize}" /> <property name="acquireIncrement" value="${pool.c3p0.acquireIncrement}" /> <property name="idleConnectionTestPeriod" value="${pool.c3p0.idleConnectionTestPeriod}" /> <property name="checkoutTimeout" value="${pool.c3p0.checkoutTimeout}" /> <property name="testConnectionOnCheckin" value="${pool.c3p0.testConnectionOnCheckin}" /> <property name="testConnectionOnCheckout" value="${pool.c3p0.testConnectionOnCheckout}" /> </bean> <!-- c3p0数据源 --> <bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClass}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="initialPoolSize" value="${pool.c3p0.initialPoolSize}" /> <property name="minPoolSize" value="${pool.c3p0.minPoolSize}" /> <property name="maxPoolSize" value="${pool.c3p0.maxPoolSize}" /> <property name="acquireIncrement" value="${pool.c3p0.acquireIncrement}" /> <property name="idleConnectionTestPeriod" value="${pool.c3p0.idleConnectionTestPeriod}" /> <property name="checkoutTimeout" value="${pool.c3p0.checkoutTimeout}" /> <property name="testConnectionOnCheckin" value="${pool.c3p0.testConnectionOnCheckin}" /> <property name="testConnectionOnCheckout" value="${pool.c3p0.testConnectionOnCheckout}" /> </bean> <!-- sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:mybatis-config.xml" /> <property name="mapperLocations" value="classpath:com/ssi/bus/mapper/**/*.xml" /> </bean> <!-- 自动配置mapper --> <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.ssi.bus.dao" /> <property name="annotationClass" value="org.springframework.stereotype.Repository"></property> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean> <!-- 事务 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 开启注解事务 --> <tx:annotation-driven transaction-manager="transactionManager" /></beans>
原因是:
在spring里使用org.mybatis.spring.mapper.MapperScannerConfigurer 进行自动扫描的时候,设置了sqlSessionFactory 的话,可能会导致PropertyPlaceholderConfigurer失效,也就是用${jdbc.username}这样之类的表达式,将无法获取到properties文件里的内容。 导致这一原因是因为,MapperScannerConigurer实际是在解析加载bean定义阶段的,这个时候要是设置sqlSessionFactory的话,会导致提前初始化一些类,这个时候,PropertyPlaceholderConfigurer还没来得及替换定义中的变量,导致把表达式当作字符串复制了。 但如果不设置sqlSessionFactory 属性的话,就必须要保证sessionFactory在spring中名称一定要是sqlSessionFactory ,否则就无法自动注入。
解决办法:
<!-- 自动配置mapper --><bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.ssi.bus.dao" /><property name="annotationClass" value="org.springframework.stereotype.Repository"></property><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property></bean>
改用sqlSessionFactoryBeanName注入就没有问题(不要使用sqlSessionFactory属性注入,使用sqlSessionFactoryBeanName注入),因为这时不会立即初始化sqlSessionFactory,传入的只是名字,非bean,所以不会引发提前初始化问题。
注意:如果你只有一个DataSource,那么就没有必要去指定SqlSessionFactory或SqlSessionTemplate,因为MapperScannerConfigurer将会创建MapperFactoryBean,之后自动装配。但是,如果你使用了一个以上的DataSource(因此,也是多个的SqlSessionFactory),那么就可以使用sqlSessionFactoryBeanName去指定sqlSessionFactory,否则自动装配可能会失效。
- MapperScannerConfigurer与<context:property-placeholder>加载顺序导致异常解决办法
- spring context:property-placeholder无法加载配置文件,导致属性无效
- spring3+mybatis 使用MapperScannerConfigurer时context:property-placeholder载不进属性
- context:property-placeholder
- context:property-placeholder
- context:property-placeholder
- context:property-placeholder
- context:property-placeholder
- context:property-placeholder
- <context:property-placeholder/>作用
- <context:property-placeholder/>使用说明
- 关于<context:property-placeholder>
- context:property-placeholder
- context:property-placeholder,spring配置文件加载属性信息
- 使用context:property-placeholder载不进属性原因分析与解决方案
- spring中context:property-placeholder
- springmvc之context:property-placeholder
- Spring properties context:property-placeholder
- cocos2d-x的一些宏定义
- linux内核--进程调度(一)
- 由Spring管理的Struts2的action的线程管理问题
- 操作系统对计算机组件的抽象概念表示
- jav设计模式之代理模式
- MapperScannerConfigurer与<context:property-placeholder>加载顺序导致异常解决办法
- C++引用的介绍
- 阶段总结 13/9/29
- 菜鸟谈谈设计模式→没有问题,只有出路
- mysql 5.0存储过程学习总结
- 三大峰会七大论坛,MDCC 2013中国移动开发者大会将在京举行
- code
- 如何学好C语言
- 一个可识别联合(Discriminated Unions)的C++实现