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的值不用占位符形式),既然都过时了那就不用了吧。

MapperScannerConfigurer之sqlSessionFactoryBeanName注入方式的更多相关文章

  1. spring四种依赖注入方式

    一.Set注入 这是最简单的注入方式,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringD ...

  2. Spring的三种通过XML实现DataSource注入方式

    Spring的三种通过XML实现DataSource注入方式: 1.使用Spring自带的DriverManagerDataSource 2.使用DBCP连接池 3.使用Tomcat提供的JNDI

  3. spring笔记--依赖注入之针对不同类型变量的几种注入方式

    控制反转和依赖注入讲的都是一个概念,只不过是站在了不同的角度,所谓的依赖注入: 是指在运行期,由外部容器动态地将依赖对象注入到组件中.当spring容器启动后,spring容器初始化,创建并管理bea ...

  4. 控制反转IOC的依赖注入方式

    引言: 项目中遇到关于IOC的一些内容,因为和正常的逻辑代码比较起来,IOC有点反常.因此本文记录IOC的一些基础知识,并附有相应的简单实例,而在实际项目中再复杂的应用也只是在基本应用的基础上扩展而来 ...

  5. spring ioc三种注入方式

    spring ioc三种注入方式 IOC ,全称 (Inverse Of Control) ,中文意思为:控制反转 什么是控制反转? 控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术. 由容 ...

  6. spring 学习之 bean 的注入方式 property和constructor-arg的使用方式

    spring 学习之 bean 的注入方式 property和constructor-arg的使用方式. bean的注入方式: property 注入是: 通过setxx方法注入. construct ...

  7. Spring IOC 注入方式

    依赖注入通常有如下两种方式: ①设值注入:IOC容器使用属性的Setter方法来注入被依赖的实例. 设值注入是指IOC容器使用属性的Setter方法来注入被依赖的实例.这种注入方式简单.直观,因而在S ...

  8. Spring 3种注入方式

    spring的三种注入方式: 接口注入(不推荐) getter,setter方式注入(比较常用) 构造器注入(死的应用) 关于getter和setter方式的注入: autowire="de ...

  9. Spring 依赖注入方式详解

    平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由 ...

随机推荐

  1. Spring Cloud分区发布实践(1) 环境准备

    最近研究了一下Spring Cloud里面的灰度发布, 看到各种各样的使用方式, 真是纷繁复杂, 眼花缭乱, 不同的场景需要不同的解决思路. 那我们也来实践一下最简单的场景: 区域划分: 服务分为be ...

  2. 组合数取模(lukas)板子

    求 C(n,m)%mo #include<bits/stdc++.h>#define re register int#define mo 10007#define ll long long ...

  3. 🏆【Java技术专区】「编译器专题」重塑认识Java编译器的执行过程(消除数组边界检查+公共子表达式)!

    前提概要 Java的class字节码并不是机器语言,要想让机器能够执行,还需要把字节码翻译成机器指令.这个过程是Java虚拟机做的,这个过程也叫编译.是更深层次的编译. 在编译原理中,把源代码翻译成机 ...

  4. C++//递增运算符重载

    1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 //重载递增运算符 6 7 //自定义 ...

  5. Convert a Private Project on bitbucket.com to a github Public Project

    Create a public repo on github, you can add README or License files on the master branch, suppose th ...

  6. Vue系列-05-项目2

    路飞学城项目 调整首页细节 固定头部 App.vue <style> body{ padding: 0; margin:0; margin-top: 80px; } </style& ...

  7. 超详细,自动化测试接入Jenkins+Sonar质量门禁实践

    大家好,我叫董鑫,一名在测试开发道路上的新手.第一阶段的学习已然结束,收获颇多,了解了很多在自己平时测试工作无法接触到的新知识,比如这次在这里分享的Sonarqube进行静态代码扫描并集成Jenkin ...

  8. deepin设置jdk全局变量

    sudo vim /etc/bash.bashrc 在文件最后边添加 JAVA_HOME=jdk地址CLASSPATH=.:$JAVA_HOME/bin.tools.jarPATH=$JAVA_HOM ...

  9. 题解 Defence

    传送门 发现最少次数只和最左,最右及中间最长的全0段有关 本来想启发式合并,结果发现直接线段树合并搭配一个类似山海经的方法就可以过了 yysy,线段树单次合并的具体复杂度并不是 \(O(logn)\) ...

  10. .net core 通过动软连接数据库

    .net core 与动软 首先创建asp.net core 或者 .net core 控制台程序.不需急着创建web.config 文件. 通过NuGet加个ado的包 System.Data.Sq ...