解决Spring使用@MapperScan问题

目录
  • 问题场景
  • 问题根源
  • 问题追溯
  • 问题解决
  • SpringBoot  @MapperScan的注意事项

问题场景

今天小编在MyBatis 整合Spring 的时候,使用到了@MapperScan,在启动期出现了一个错误:

Invalid default: public abstract java.lang.Class org.mybatis.spring.annotation.MapperScan.factoryBean()

对于这个错误,小编也是倍感无奈,怎么会出现这个错误呢,看一下我的依赖有没有错误:

    compile(project(":spring-context"))
//    compile(project(":spring-instrument"))
    // https://mvnrepository.com/artifact/cglib/cglib
    compile group: 'cglib', name: 'cglib', version: '2.2.2'
    // https://mvnrepository.com/artifact/mysql/mysql-connector-java
    compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.21'
    // https://mvnrepository.com/artifact/org.mybatis/mybatis
    compile group: 'org.mybatis', name: 'mybatis', version: '3.5.2'
    // https://mvnrepository.com/artifact/org.mybatis/mybatis-spring
    compile group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.2'

完全没得毛病呀,他妈的,究竟是哪里出现了问题呢,小编这时将SpringFramework 源码从github 上clone 下来了,导入idea 开始寻找问题所在。。。

问题根源

经过不懈的努力,小编终于找到了问题根源,在AnnotationsScanner 类中的这个方法:

static Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defensive) {
  boolean cached = false;
  Annotation[] annotations = declaredAnnotationCache.get(source);
  if (annotations != null) {
   cached = true;
  }
  else {
   // 使用@MapperScan 的时候会报错,引入spring-jdbc 即可
   // 具体原因暂时还不清楚
   // Invalid default: public abstract java.lang.Class org.mybatis.spring.annotation.MapperScan.factoryBean()
   annotations = source.getDeclaredAnnotations();
   if (annotations.length != 0) {
    boolean allIgnored = true;
    for (int i = 0; i < annotations.length; i++) {
     Annotation annotation = annotations[i];
     if (isIgnorable(annotation.annotationType()) ||
       !AttributeMethods.forAnnotationType(annotation.annotationType()).isValid(annotation)) {
      annotations[i] = null;
     }
     else {
      allIgnored = false;
     }
    }
    annotations = (allIgnored ? NO_ANNOTATIONS : annotations);
    if (source instanceof Class || source instanceof Member) {
     declaredAnnotationCache.put(source, annotations);
     cached = true;
    }
   }
  }
  if (!defensive || annotations.length == 0 || !cached) {
   return annotations;
  }
  return annotations.clone();
 }

AnnotatedElement 对于这个类,小编也是不太清楚,这时也倍感无奈,这个方法主要做的事情就是将Appconfig 配置类中的注解扫描下来,那会不会是注解的问题呢,在@MapperScan 注解的注释中发现小编的代码与MyBatis-Spring 开发团队提供的实例代码一致,这就让人想不明白了:

 * <pre class="code">
 * @Configuration
 * @MapperScan("org.mybatis.spring.sample.mapper")
 * public class AppConfig {
 *
 *   @Bean
 *   public DataSource dataSource() {
 *     return new EmbeddedDatabaseBuilder().addScript("schema.sql").build();
 *   }
 *
 *   @Bean
 *   public DataSourceTransactionManager transactionManager() {
 *     return new DataSourceTransactionManager(dataSource());
 *   }
 *
 *   @Bean
 *   public SqlSessionFactory sqlSessionFactory() throws Exception {
 *     SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
 *     sessionFactory.setDataSource(dataSource());
 *     return sessionFactory.getObject();
 *   }
 * }
 * </pre>

问题追溯

我这个时候被起疯了都,从GitHub 上由把mybatis-spring 的源码clone 了下来,导入idea,首先看一下mybatis-spring 的依赖:

 <dependencies>
    <!-- Compile dependencies -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.batch</groupId>
      <artifactId>spring-batch-infrastructure</artifactId>
      <version>${spring-batch.version}</version>
      <scope>provided</scope>
    </dependency>

从依赖中看到了什么,tmd,<scope>provided</scope>,这个怎么讲,太无语了,其中它引入了spring-jdbc 的依赖。想象一下,@MapperScan 注解中是不是也使用到了spring-jdbc 的类,然后在使用@MapperScan 的时候没有加入spring-jdbc 的依赖,导致注解在扫描期间的错误,没毛病解释的通,找一下@MapperScan 中是否使用到了spring-jdbc 的依赖。

问题解决

果不其然,下面用一张图来看吧。

所以呢,在项目中加入spring-jdbc 完美解决。

SpringBoot  @MapperScan的注意事项

错误代码如下:

[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis.mapper.provider.base.BaseSelectProvider.dynamicSQL). Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.base.BaseSelectProvider] with root cause

检查@MapperScan导入的包是否为

import tk.mybatis.spring.annotation.MapperScan;

切记不要导成

import org.mybatis.spring.annotation.MapperScan

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 浅谈@mapper引入不到引入的是@MapperScan的问题

    两种防水都可以,但是使用方式不同. @mapper需要mybatis和mybatis-spring的版本足够的高才可以. 不然导入不到@mapper. 补充知识:关于MyBatis的@Mapper和@MapperScan注解的一点思考 最近有空回顾mybatis,想起@Mapper注解一直没弄明白是干嘛的,代码上的注释写的很简单(Marker interface for MyBatis mappers),开发过程中也没用到,但网上各种资料偶有出现他的身影.问了度娘,都没讲清楚,我决定自己思考下这

  • @MapperScan注解与@Mapper注解的使用

    目录 @MapperScan注解与@Mapper注解使用 MapperScan注解和@Mapper的区别 @MapperScan注解与@Mapper注解使用 @Mapper一般对应一个接口,相当于一个mapper.xml文件,它的作用就是将接口生成一个动态代理类. 当我们写的mapper接口比较多的时候,我们没必须花太多时间一个一个的写,这样写太麻烦了,我们可以使用@ManpperScan注解,指明要扫描的包,它可以扫描所有的mapper文件. 它是如何做到的,我们可以查看里面的源码,主要起作用

  • MyBatis中Mapper的注入问题详解

    在 SpringBoot 体系中,MyBatis 对 Mapper 的注入常见的方式我知道的有 2 种: 1.@MapperScan MapperScan 类是 mybatis-spring 包里面的. 通过在启动类上使用 @MapperScan,然后通过 basePackages 属性指定 Mapper 文件所在的目录来进行扫描装载,默认情况下指定目录下的所有.java文件都会被当做 Mapper 来加载处理. @MapperScan(basePackages = "com.test.spri

  • 基于@MapperScan和@ComponentScan的使用区别

    目录 @MapperScan和@ComponentScan区别 @MapperScan和@ComponentScan使用 原因 解决办法 课外拓展 @MapperScan和@ComponentScan区别 今天在撸SpringBoot的时候,突然对注解产生了混淆,@MapperScan和@ComponentScan都是扫描包,二者之间有什么区别呢? 首先,@ComponentScan是组件扫描注解,用来扫描@Controller @Service @Repository这类,主要就是定义扫描的路

  • 解决Spring使用@MapperScan问题

    目录 问题场景 问题根源 问题追溯 问题解决 SpringBoot  @MapperScan的注意事项 问题场景 今天小编在MyBatis 整合Spring 的时候,使用到了@MapperScan,在启动期出现了一个错误: Invalid default: public abstract java.lang.Class org.mybatis.spring.annotation.MapperScan.factoryBean() 对于这个错误,小编也是倍感无奈,怎么会出现这个错误呢,看一下我的依赖

  • 解决Spring boot整合mybatis,xml资源文件放置及路径配置问题

    网上各种解决方案,我试了好久,整合了几篇文章才凑出来,在这里分享一下,实在不想网友们在这里面绕圈子,毕竟,写代码的时间是愉快的,解决bug也是愉快的,但也是一直在bug里面绕圈子就不爽了. 亲自试验: 1) 我的mapper和xml是这样子放置的 2) 在.xml中namespace是这样的: 3) application.properties中mybatis.mapper-locations得这么配置到xml 4) 最后呢,你只要在pom.xml中build下这样配置 5) 按照我这种位置防止

  • 彻底解决Spring MVC中文乱码问题的方案

    乱码是让人很头疼的一件事,本文介绍了彻底解决Spring MVC中文乱码问题的方案,具体如下:  1:表单提交controller获得中文参数后乱码解决方案 注意:  jsp页面编码设置为UTF-8 form表单提交方式为必须为post,get方式下面spring编码过滤器不起效果 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <form

  • 解决Spring Boot 在localhost域奇怪的404问题(Mac book pro)

    在mac系统中,明明url是对的,浏览器也可以打开,一个简单的代码调用就是404,你有没有遇到过? 情景再现 普通的一个controller,返回一个常量. @GetMapping("/project_metadata/spring-boot") public String getMetadata(){ return "{\"data\":1234}";//这个不重要 } 调用接口的方式: content = new JSONObject(res

  • 解决Spring Mvc中对象绑定参数重名的问题

    前言 本文主要给大家介绍了关于解决Spring Mvc对象绑定参数重名问题的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 发现问题 SpringMvc提供了对象参数绑定功能,例如Person对象有一个age字段, 则页面表单使用 <input type='text' name='age' value='25'> Controller中使用 public void getPerson(Person person){ // 此时person对象的age属性值为25 }

  • 解决spring mvc 多数据源切换,不支持事务控制的问题

    一个项目中需要使用两个数据库,Oracle 和Mysql,于是参考各个blog,实现此功能.写好后才发现,原来的事务失效了,我去... spring-mybatis.xml 配置 <bean id="configReader" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"> <property name="location

  • 解决spring mvc 返回json数据到ajax报错parseerror问题

    最近使用ajax接收spring mvc传过来的json数据时总是出现parseerror的错误,错误源码如下: 前端: $.ajax({ type: 'POST', url: "groupFunctionEdit", dataType: 'json', contentType: "application/json", data: JSON.stringify(functiondata), success: function(data){ alert('数据加载成功

  • 完美解决spring websocket自动断开连接再创建引发的问题

    问题:由于 web session 超时时间为 30 分钟,如用户在 web session 规定时间内没有退出系统,但由于其它原因 用户却断开的 websocket 的连接,如果用户还要聊天或是其它 websocket 方面的操作,那么就只能重新连接... 看代码: var socket; var $ = function() { return document.getElementById(arguments[0]); } var log = function(msg) { $("log&q

  • 完美解决Spring声明式事务不回滚的问题

    疑问,确实像往常一样在service上添加了注解 @Transactional,为什么查询数据库时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚.于是就对相关代码进行了一番测试,结果发现一下踩进了两个坑,确实是事务未回滚导致的数据不一致. 下面总结一下经验教训: Spring事务的管理操作方法 编程式的事务管理 实际应用中很少使用 通过使用TransactionTemplate 手动管理事务 声明式的事务管理 开发中推荐使用(代码侵入最少) Spring的声明式事

  • 解决spring boot 1.5.4 配置多数据源的问题

    spring boot 已经支持多数据源配置了,无需网上好多那些编写什么类的,特别麻烦,看看如下解决方案,官方的,放心! 1.首先定义数据源配置 #=====================multiple database config============================ #ds1 first.datasource.url=jdbc:mysql://localhost/test?characterEncoding=utf8&useSSL=true first.datasou

随机推荐