MapperScannerConfigurer之sqlSessionFactoryBeanName注入方式


Spring整合Mybatis時,項目啟動時報錯:(MapperScannerConfigurer之sqlSessionFactoryBeanName注入方式)

pringframework.beans.factory.BeanCreationException: Error creating bean with name 'mapperScannerConfigurer'defined in class path resource [applicationContext.xml]: 
Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sqlSessionFactory';
 nested exception is org.springframework.beans.factory BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext.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 [applicationContext.xml]: Error setting property values;
nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'driverClassName' threw exception;
 nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [${driver}]

可以看到報的大大小小錯誤共有5個錯誤:

pringframework.beans.factory.BeanCreationException:創建名為“mapperScannerConfigurer”的bean時出錯,該bean在類路徑資源[applicationContext.xml]中定義:
設置bean屬性“sqlSessionFactory”時無法解析對bean“sessionFactory”的引用;
嵌套異常為org.springframework.beans.factory BeanCreationException:創建名為“sessionFactory”的bean時出錯,該bean在類路徑資源[applicationContext.xml]中定義:
無法解析對bean的引用
設置bean屬性“dataSource”時使用“dataSource”;
嵌套異常為org.springframework.beans.factory.BeanCreationException:創建名為“dataSource”的bean時出錯,該bean在類路徑資源[applicationContext.xml]中定義:設置屬性值時出錯;
嵌套的異常是org.springframework.beans.PropertyBatchUpdateException;嵌套的PropertyAccessException(1)是:PropertyAccessException 1:org.springframework.beans.MethodInvocationException:Property'driverClassName'拋出異常;
嵌套異常為java.lang.IllegalStateException:無法加載JDBC驅動程序類[${driver}]

ok,那么下面是我的Spring配置文件的源代碼

<context:property-placeholder location="classpath:/jdbc.properties"/>
<!-- 配置數據源bean -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="password" value="${password}"/>
        <property name="username" value="${user}"/>
    </bean>
    <!-- SqlSessionFactory的bean -->
    <bean name="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 掃描Mapper文件 -->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactory" ref="sessionFactory"/>
        <property name="basePackage" value="com.lyl.mapper"/>
    </bean>

通過分析日志提供的報錯信息,發現跟本的原因時因為程序沒有加載JDBC的驅動,也就是數據源bean中的driverClassName沒有加載成功,因為我這里采用的是jdbc.properties的方式來加載數據源參數信息,所有我一開是懷疑的是文件的驅動路徑寫錯了或者jdbc的包沒有導入環境中,但是折騰后面發現一切正常,於是索性的將${driver}直接替換成文件中的參數,引入改成手寫,啟動項目,竟然發現啟動成功!,這讓我百思不得其解,於是開始漫長的百度,找不到我想要的答案,便再看一遍日志,發現是因為配置sqlSessionFactorybean時,dataSource出錯找不到JDBC驅動,既然JDBC驅動沒有毛病,sqlSessionFactory也不可能出毛病,於是我就將目光鎖定到了mapperScannerConfigurerbean,因為他注入了沒有毛病的SQL Session Factory,然后就是開始百度,果然,找對了錯誤答案一下就出來了。
原來的mapperScannerConfigurerbean:

<!-- 掃描Mapper文件 -->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactory" ref="sessionFactory"/>
        <property name="basePackage" value="com.lyl.mapper"/>
    </bean>

修改后的mapperScannerConfigurerbean:

  <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
<!--        <property name="sqlSessionFactory" ref="sessionFactory"/>-->
        <property name="basePackage" value="com.lyl.mapper"/>
    </bean>

可以發現,不再注入sqlSessionFactory的屬性,取而代之的是sqlSessionFactoryBeanName屬性,並且用的是value來賦值,程序能夠正常run。
那么問題是解決了,原理是什么呢?我又百度了sqlSessionFactoryBeanName這的個屬性。

發現在MapperScannerConfigurer中有4種注入方式,而sqlSessionFactory的注入方式已經過時了,而造成本次報錯的根本原因出現在MapperScannerConfigurer上:

在mybatis-spring1.1.0之前,是經過 將SqlSessionFactory對象注入到sqlSessionFactory,這樣作可能會有一個問題, 就是在初始化MyBatis時,jdbc.properties文件還沒被加載進來,dataSource的屬性值沒有被替換,就開始構造sqlSessionFactory類,屬性值就會加載失敗。在1.1.0之后,MapperScannerConfigure提供了String類型的sqlSessionFactoryBeanName,這樣將bean name注入到sqlSessionFactoryBeanName,這樣就會等到spring初始化完成后,再構建sqlSessionFactory。

終於找到了錯誤本質了,折騰了大半天!發現原來是jdbc.properties文件和SqlSessionFactory出現了沖突,在MapperScannerConfigurer中直接注入sqlSessionFactory屬性,如果使用的是占位符去配置dataSourcebean,那么可能會造成sqlSessionFactory構建先於jdbc.properties文件的加載。

目前還沒有找到用sqlSessionFactory來注入成功的解決方法(除非直接寫jdbc的值不用占位符形式),既然都過時了那就不用了吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM