摘要:在SpringBoot运行测试Mybatis-Plus测试的时候报错的问题分析与修复

本文分享自华为云社区《SpringBoot整合MybatisPlus项目存在Mapper时运行报错的问题分析与修复》,作者:攻城狮Chova 。

异常信息

  • 在SpringBoot运行测试Mybatis-Plus测试的时候报错:
  1. rg.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.oxford.test.ApplicationTests':

原因

  • 自定义的mapper文件不受Spring管理所以不会注入到Spring容器中
  • mybatis-config中只是会为对应的mapper创建代理类
  • 想真正包装成bean, 注入到spring容器中,需要使用到AutoConfiguredMapperScannerRegistrar它会根据扫描 @Mapper注释或是 @MapperScan指定的包下的接口,将其注册为bean

AutoConfiguredMapperScannerRegistrar:

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5.  
  6. package com.baomidou.mybatisplus.spring.boot.starter;
  7.  
  8. import com.baomidou.mybatisplus.MybatisConfiguration;
  9. import com.baomidou.mybatisplus.MybatisXMLLanguageDriver;
  10. import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
  11. import java.util.Iterator;
  12. import java.util.List;
  13. import javax.annotation.PostConstruct;
  14. import javax.sql.DataSource;
  15. import org.apache.ibatis.annotations.Mapper;
  16. import org.apache.ibatis.logging.Log;
  17. import org.apache.ibatis.logging.LogFactory;
  18. import org.apache.ibatis.mapping.DatabaseIdProvider;
  19. import org.apache.ibatis.plugin.Interceptor;
  20. import org.apache.ibatis.session.ExecutorType;
  21. import org.apache.ibatis.session.SqlSessionFactory;
  22. import org.mybatis.spring.SqlSessionTemplate;
  23. import org.mybatis.spring.mapper.ClassPathMapperScanner;
  24. import org.mybatis.spring.mapper.MapperFactoryBean;
  25. import org.springframework.beans.BeansException;
  26. import org.springframework.beans.factory.BeanFactory;
  27. import org.springframework.beans.factory.BeanFactoryAware;
  28. import org.springframework.beans.factory.ObjectProvider;
  29. import org.springframework.beans.factory.support.BeanDefinitionRegistry;
  30. import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
  31. import org.springframework.boot.autoconfigure.AutoConfigureAfter;
  32. import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
  33. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  34. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  35. import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  36. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  37. import org.springframework.context.ResourceLoaderAware;
  38. import org.springframework.context.annotation.Bean;
  39. import org.springframework.context.annotation.Configuration;
  40. import org.springframework.context.annotation.Import;
  41. import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
  42. import org.springframework.core.io.Resource;
  43. import org.springframework.core.io.ResourceLoader;
  44. import org.springframework.core.type.AnnotationMetadata;
  45. import org.springframework.util.Assert;
  46. import org.springframework.util.CollectionUtils;
  47. import org.springframework.util.ObjectUtils;
  48. import org.springframework.util.StringUtils;
  49.  
  50. @Configuration
  51. @ConditionalOnClass({SqlSessionFactory.class, MybatisSqlSessionFactoryBean.class})
  52. @ConditionalOnBean({DataSource.class})
  53. @EnableConfigurationProperties({MybatisPlusProperties.class})
  54. @AutoConfigureAfter({DataSourceAutoConfiguration.class})
  55. public class MybatisPlusAutoConfiguration {
  56. private static final Log logger = LogFactory.getLog(MybatisPlusAutoConfiguration.class);
  57. private final MybatisPlusProperties properties;
  58. private final Interceptor[] interceptors;
  59. private final ResourceLoader resourceLoader;
  60. private final DatabaseIdProvider databaseIdProvider;
  61. private final List<ConfigurationCustomizer> configurationCustomizers;
  62.  
  63. public MybatisPlusAutoConfiguration(MybatisPlusProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
  64. this.properties = properties;
  65. this.interceptors = (Interceptor[])interceptorsProvider.getIfAvailable();
  66. this.resourceLoader = resourceLoader;
  67. this.databaseIdProvider = (DatabaseIdProvider)databaseIdProvider.getIfAvailable();
  68. this.configurationCustomizers = (List)configurationCustomizersProvider.getIfAvailable();
  69. }
  70.  
  71. @PostConstruct
  72. public void checkConfigFileExists() {
  73. if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
  74. Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
  75. Assert.state(resource.exists(), "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)");
  76. }
  77.  
  78. }
  79.  
  80. @Bean
  81. @ConditionalOnMissingBean
  82. public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
  83. MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
  84. factory.setDataSource(dataSource);
  85. factory.setVfs(SpringBootVFS.class);
  86. if (StringUtils.hasText(this.properties.getConfigLocation())) {
  87. factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
  88. }
  89.  
  90. MybatisConfiguration configuration = this.properties.getConfiguration();
  91. if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
  92. configuration = new MybatisConfiguration();
  93. }
  94.  
  95. if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
  96. Iterator i$ = this.configurationCustomizers.iterator();
  97.  
  98. while(i$.hasNext()) {
  99. ConfigurationCustomizer customizer = (ConfigurationCustomizer)i$.next();
  100. customizer.customize(configuration);
  101. }
  102. }
  103.  
  104. configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
  105. factory.setConfiguration(configuration);
  106. if (this.properties.getConfigurationProperties() != null) {
  107. factory.setConfigurationProperties(this.properties.getConfigurationProperties());
  108. }
  109.  
  110. if (!ObjectUtils.isEmpty(this.interceptors)) {
  111. factory.setPlugins(this.interceptors);
  112. }
  113.  
  114. if (this.databaseIdProvider != null) {
  115. factory.setDatabaseIdProvider(this.databaseIdProvider);
  116. }
  117.  
  118. if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
  119. factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
  120. }
  121.  
  122. if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) {
  123. factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage());
  124. }
  125.  
  126. if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
  127. factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
  128. }
  129.  
  130. if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
  131. factory.setMapperLocations(this.properties.resolveMapperLocations());
  132. }
  133.  
  134. if (!ObjectUtils.isEmpty(this.properties.getGlobalConfig())) {
  135. factory.setGlobalConfig(this.properties.getGlobalConfig().convertGlobalConfiguration());
  136. }
  137.  
  138. return factory.getObject();
  139. }
  140.  
  141. @Bean
  142. @ConditionalOnMissingBean
  143. public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
  144. ExecutorType executorType = this.properties.getExecutorType();
  145. return executorType != null ? new SqlSessionTemplate(sqlSessionFactory, executorType) : new SqlSessionTemplate(sqlSessionFactory);
  146. }
  147.  
  148. @Configuration
  149. @Import({MybatisPlusAutoConfiguration.AutoConfiguredMapperScannerRegistrar.class})
  150. @ConditionalOnMissingBean({MapperFactoryBean.class})
  151. public static class MapperScannerRegistrarNotFoundConfiguration {
  152. public MapperScannerRegistrarNotFoundConfiguration() {
  153. }
  154.  
  155. @PostConstruct
  156. public void afterPropertiesSet() {
  157. MybatisPlusAutoConfiguration.logger.debug("No " + MapperFactoryBean.class.getName() + " found.");
  158. }
  159. }
  160.  
  161. public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
  162. private BeanFactory beanFactory;
  163. private ResourceLoader resourceLoader;
  164.  
  165. public AutoConfiguredMapperScannerRegistrar() {
  166. }
  167.  
  168. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  169. MybatisPlusAutoConfiguration.logger.debug("Searching for mappers annotated with @Mapper");
  170. ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
  171.  
  172. try {
  173. if (this.resourceLoader != null) {
  174. scanner.setResourceLoader(this.resourceLoader);
  175. }
  176.  
  177. List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
  178. if (MybatisPlusAutoConfiguration.logger.isDebugEnabled()) {
  179. Iterator i$ = packages.iterator();
  180.  
  181. while(i$.hasNext()) {
  182. String pkg = (String)i$.next();
  183. MybatisPlusAutoConfiguration.logger.debug("Using auto-configuration base package '" + pkg + "'");
  184. }
  185. }
  186.  
  187. scanner.setAnnotationClass(Mapper.class);
  188. scanner.registerFilters();
  189. scanner.doScan(StringUtils.toStringArray(packages));
  190. } catch (IllegalStateException var7) {
  191. MybatisPlusAutoConfiguration.logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled." + var7);
  192. }
  193.  
  194. }
  195.  
  196. public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  197. this.beanFactory = beanFactory;
  198. }
  199.  
  200. public void setResourceLoader(ResourceLoader resourceLoader) {
  201. this.resourceLoader = resourceLoader;
  202. }
  203. }
  204. }

解决办法

@Mapper

  • 在mapper文件的类上添加 @Mapper注解

@MapperScan

  • 在主类上添加 @MapperScan注解,指定mapper的扫描范围,注意值为mapper文件所在的包名
  1. @MapperScan("com.oxford.mapper")

点击关注,第一时间了解华为云新鲜技术~

实践丨SpringBoot整合Mybatis-Plus项目存在Mapper时报错的更多相关文章

  1. SpringBoot整合Mybatis之项目结构、数据源

    已经有好些日子没有总结了,不是变懒了,而是我一直在奋力学习springboot的路上,现在也算是完成了第一阶段的学习,今天给各位总结总结. 之前在网上找过不少关于springboot的教程,都是一些比 ...

  2. springboot 测试类,项目使用shiro时报错UnavailableSecurityManagerException

    大概的问题就是,正常运行项目是没有问题的 使用测试类是,加载不了shiro的securityManager,主要导致不是很清楚,望告知, 解决方法 @Resource org.apache.shiro ...

  3. springboot整合mybatis源码分析

    springboot整合mybatis源码分析 本文主要讲述mybatis在springboot中是如何被加载执行的,由于涉及的内容会比较多,所以这次只会对调用关系及关键代码点进行讲解,为了避免文章太 ...

  4. springBoot 整合 mybatis 项目实战

    二.springBoot 整合 mybatis 项目实战   前言 上一篇文章开始了我们的springboot序篇,我们配置了mysql数据库,但是我们sql语句直接写在controller中并且使用 ...

  5. 三、SpringBoot 整合mybatis 多数据源以及分库分表

    前言 说实话,这章本来不打算讲的,因为配置多数据源的网上有很多类似的教程.但是最近因为项目要用到分库分表,所以让我研究一下看怎么实现.我想着上一篇博客讲了多环境的配置,不同的环境调用不同的数据库,那接 ...

  6. 【java框架】SpringBoot(7) -- SpringBoot整合MyBatis

    1.整合MyBatis操作 前面一篇提到了SpringBoot整合基础的数据源JDBC.Druid操作,实际项目中更常用的还是MyBatis框架,而SpringBoot整合MyBatis进行CRUD也 ...

  7. SpringBoot整合Mybatis【非注解版】

    接上文:SpringBoot整合Mybatis[注解版] 一.项目创建 新建一个工程 ​ 选择Spring Initializr,配置JDK版本 ​ 输入项目名 ​ 选择构建web项目所需的state ...

  8. springboot学习随笔(四):Springboot整合mybatis(含generator自动生成代码)

    这章我们将通过springboot整合mybatis来操作数据库 以下内容分为两部分,一部分主要介绍generator自动生成代码,生成model.dao层接口.dao接口对应的sql配置文件 第一部 ...

  9. springBoot整合mybatis、jsp 或 HTML

    springBoot整合mybatis.jsp Spring Boot的主要优点: 1:  为所有Spring开发者更快的入门: 2:  开箱即用,提供各种默认配置来简化项目配置: 3:  内嵌式容器 ...

随机推荐

  1. Linux基础:VLAN篇

    一.二层基础知识 1.1 vlan介绍 本小节重点: vlan的含义 vlan的类型 交换机端口类型 vlan的不足 1.1.1 vlan的含义 局域网LAN的发展是VLAN产生的基础,因而先介绍一下 ...

  2. CentOS 7 下编译安装 4.14 内核

    文章目录 rpm升级 编译升级 升级前 下载安装包 编译内核 更新启动引导 修改默认启动内核 重启之后验证 rpm升级 # rpm的方式升级内核 1.载入内核公钥 [root@localhost ~] ...

  3. c++ 文本处理

    c++ 文本处理 1.使用sstream版本 (1)功能:截取第一列为1以后的数据,如下图,截取第5行(包括第5行)以后的数据,前面4行数据丢弃. (2)代码:textProc.cc #include ...

  4. kaptcha验证码参数设置

    Constant 描述 默认值 kaptcha.border 图片边框,合法值:yes , no yes kaptcha.border.color 边框颜色,合法值: r,g,b (and optio ...

  5. [编译器]dev c++单步调试

    一.dev c++调试崩溃的解决方案 1.点击"工具 -> 编译选项". 2.选择"编译器"选项卡,勾选"编译时加入以下命令",输入& ...

  6. ASP.NET Core 6框架揭秘实例演示[13]:日志的基本编程模式[上篇]

    <诊断跟踪的几种基本编程方式>介绍了四种常用的诊断日志框架.其实除了微软提供的这些日志框架,还有很多第三方日志框架可供我们选择,比如Log4Net.NLog和Serilog 等.虽然这些框 ...

  7. maven配置本地仓库和远程仓库

    配置本地仓库 修改maven安装目录下conf/settings.xml,也可以在idea配置中覆盖 <localRepository>E:\maven\MavenRepository&l ...

  8. mapreduce 中 groupingComparator 用法

    groupingComparator是对reduce输入的数据进行分组,比如 public int compare(WritableComparable a, WritableComparable b ...

  9. C++ 部分函数

    string库 1.size()与length() 字符串长,结果相同 string s; s.length(); //s.length()-1是最后一个字符的下标,而不是'\0' for(i=0;i ...

  10. ROS入门介绍

    1.ROS版本介绍 ROS版本:(已经推出数十个版本) 2013 ------> Hydro 2014 ------> Indigo (对应Ubuntu14.04) (现在已经基本废弃) ...