Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring

Mybatis在与Spring集成的时候可以配置              MapperFactoryBean来生成Mapper接口的代理. 例如

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"><property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" /><property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

 

MapperFactoryBean 创建的代理类实现了 UserMapper 接口,并且注入到应用程序中。 因为代理创建在运行时环境中(Runtime,译者注) ,那么指定的映射器必须是一个接口,而 不是一个具体的实现类。

上面的配置有一个很大的缺点,就是系统有很多的配置文件时 全部需要手动编写,所以上述的方式已经很用了。

没有必要在 Spring 的 XML 配置文件中注册所有的映射器。相反,你可以使用一个 MapperScannerConfigurer , 它 将 会 查 找 类 路 径 下 的 映 射 器 并 自 动 将 它 们 创 建 成 MapperFactoryBean。

要创建 MapperScannerConfigurer,可以在 Spring 的配置中添加如下代码:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="org.mybatis.spring.sample.mapper" />
</bean>

 

basePackage 属性是让你为映射器接口文件设置基本的包路径。 你可以使用分号或逗号 作为分隔符设置多于一个的包路径。每个映射器将会在指定的包路径中递归地被搜索到。

注 意 , 没 有 必 要 去 指 定 SqlSessionFactory 或 SqlSessionTemplate , 因 为 MapperScannerConfigurer 将会创建 MapperFactoryBean,之后自动装配。但是,如果你使 用了一个 以上的 DataSource ,那 么自动 装配可 能会失效 。这种 情况下 ,你可 以使用 sqlSessionFactoryBeanName 或 sqlSessionTemplateBeanName 属性来设置正确的 bean 名 称来使用。这就是它如何来配置的,注意 bean 的名称是必须的,而不是 bean 的引用,因 此,value 属性在这里替代通常的 ref:

<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />

MapperScannerConfigurer 支 持 过 滤 由 指 定 的 创 建 接 口 或 注 解 创 建 映 射 器 。 annotationClass 属性指定了要寻找的注解名称。 markerInterface 属性指定了要寻找的父 接口。如果两者都被指定了,加入到接口中的映射器会匹配两种标准。默认情况下,这两个 属性都是 null,所以在基包中给定的所有接口可以作为映射器加载。

被发现的映射器将会使用 Spring 对自动侦测组件(参考 Spring 手册的 3.14.4)默认的命 名策略来命名。也就是说,如果没有发现注解,它就会使用映射器的非大写的非完全限定类 名。但是如果发现了@Component 或 JSR-330 的@Named 注解,它会获取名称。注意你可以 配 置 到 org.springframework.stereotype.Component , javax.inject.Named(如果你使用 JSE 6 的话)或你自己的注解(肯定是自我注解)中,这 样注解将会用作生成器和名称提供器。

接下来让我们看一下MapperScannerConfigurer类的源码 看看是如何自动扫描的。

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {2     if (this.processPropertyPlaceHolders) {3       processPropertyPlaceHolders();4     }5 6     ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);7     scanner.setAddToConfig(this.addToConfig);8     scanner.setAnnotationClass(this.annotationClass);9     scanner.setMarkerInterface(this.markerInterface);
10     scanner.setSqlSessionFactory(this.sqlSessionFactory);
11     scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
12     scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
13     scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
14     scanner.setResourceLoader(this.applicationContext);
15     scanner.setBeanNameGenerator(this.nameGenerator);
16     scanner.registerFilters();
17     scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
18   }把Mapper接口转换成MapperFactoryBean的代码在地17行这个方法里,让我们跟踪进去看一下。  1   @Override2   public Set<BeanDefinitionHolder> doScan(String... basePackages) {3     Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);4 5     if (beanDefinitions.isEmpty()) {6       logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");7     } else {8       for (BeanDefinitionHolder holder : beanDefinitions) {9         GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
10
11         if (logger.isDebugEnabled()) {
12           logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName()
13               + "' and '" + definition.getBeanClassName() + "' mapperInterface");
14         }
15
16         // the mapper interface is the original class of the bean
17         // but, the actual class of the bean is MapperFactoryBean
18         //把接口的类型设置进去
19         definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());
20         //设置Bean的真实类型MapperFactoryBean
21         definition.setBeanClass(MapperFactoryBean.class);
22         //是否把Mapper接口加入到Mybatis的Config当中去
23         definition.getPropertyValues().add("addToConfig", this.addToConfig);
24
25         boolean explicitFactoryUsed = false;
26         //如果sqlSessionFactoryBeanName的名字不为空 则在Spring容器中查询
27         //适合多数据源
28         if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
29           definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
30           explicitFactoryUsed = true;
31         } else if (this.sqlSessionFactory != null) {
32           definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
33           explicitFactoryUsed = true;
34         }
35
36         //如果sqlSessionTemplateBeanName的名字不为空 则在Spring容器中查询
37         //适合多数据源
38         if (StringUtils.ha
39         if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
40           if (explicitFactoryUsed) {
41             logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
42           }
43           definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
44           explicitFactoryUsed = true;
45         } else if (this.sqlSessionTemplate != null) {
46           if (explicitFactoryUsed) {
47             logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
48           }
49           definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
50           explicitFactoryUsed = true;
51         }
52
53         if (!explicitFactoryUsed) {
54           if (logger.isDebugEnabled()) {
55             logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
56           }
57           definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
58         }
59       }
60     }
61     //这个集合返回以后 Spring容器会将里面的所有内容注册到容器中
62     return beanDefinitions;
63   }

 

转载于:https://www.cnblogs.com/xiohao/p/4701036.html

Mybatis下面的MapperScannerConfigurer 扫描器相关推荐

  1. 解决spring整合mybatis时错误 ‘org.mybatis.spring.mapper.MapperScannerConfigurer#0‘

    警告:org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.mybat ...

  2. sonarqube中,分析maven聚合工程时,不必分析parent工程,只需分析下面的module子工程即可

    sonarqube中,分析maven聚合工程时,不必分析parent工程,只需分析下面的module子工程即可 cd ../../xxx-sms # mvn clean org.jacoco:jaco ...

  3. Java黑皮书课后题第8章:*8.30(代数:解答线性方程)编写一个方法,解答下面的2*2线性方程组系统

    *8.30(代数:解答线性方程)编写一个方法,解答下面的2*2线性方程组系统 题目 题目描述 代码 题目 题目描述 8.30(代数:解答线性方程)编写一个方法,解答下面的22线性方程组系统: a00 ...

  4. Java黑皮书课后题第5章:**5.35(加法)编写程序,计算下面的和:1/(1+根2) + 1/(根2+根3) + 1/(根3+根4)+……1/(根624+根625)

    @[TOC](5.35(加法)编写程序,计算下面的和:1/(1+根2) + 1/(根2+根3) + 1/(根3+根4)+--1/(根624+根625)) 题目 题目概述 5.35(加法)编写程序,计算 ...

  5. windows下面的txt在linux下面显示为乱码

    windows下面的txt正确保存操作后, 传递到linux,发现是乱码. 解决方案: linux下面,整个txt文件拖入chrome浏览器,然后把浏览器里面的内容重新保存即可

  6. Ubuntu16.04下面的vs code出现Unable to activate CppCheck analyzer

    Ubuntu16.04下面的vs code出现Unable to activate CppCheck analyzer 解决方案: synaptic管理器中安装cppcheck和cppcheck-gu ...

  7. Android之非root手机run-as命令获取debug版本apk里面的数据(shared_prefs文件,lib下面的so,数据库文件)

    1  问题 非root手机想要获取debug版本的apk里面的数据(shared_prefs文件,lib下面的so,数据库文件) 2  直接用run-as命令 adb shellrun-as pack ...

  8. 根据div 标签 查看数组@class=modulwrap 下面的/table/tbody/tr/td

    <div class="modulwrap"><div class="request_title"><span class=&qu ...

  9. java 下面的while语句退出时_java 下面的while语句退出时

    java 下面的while语句退出时 [2021-02-02 07:01:21]  简介: php中while循环语句的使用方法是:while循环语句在指定条件为true时执行代码块.while循环语 ...

  10. linux下面的j2sdk的安装和配置过程

    linux下面的j2sdk的安装和配置过程! 1.下载一个Linux Platform的JDK,建议下载RPM自解压格式的 (RPM in self-extracting file,j2sdk-1_4 ...

最新文章

  1. Windows 各种计时函数总结
  2. openresty开发系列24--openresty中lua的引入及使用
  3. sqlite 字符串 转 整型 cast 函数 (强制类型转换 )
  4. 软件工程综合实践专题——个人博客作业1
  5. 【nyoj-456】 邮票分你一半 (dp,0-1背包的中点问题)
  6. php多线程模拟请求,浅谈php使用curl模拟多线程发送请求
  7. 视频下载比想象中容易
  8. inno setup打包的安装包如何在卸载完程序后可以继续安装_这两个方法就够了!快速制作Python程序Windows安装包...
  9. PostgreSQL数据库远程连接功能的开启
  10. 自由在博客里插入广告,有钱你不赚吗???
  11. oracle掉电后ora 00600,ORA-00600: 内部错误代码, 参数: [kcratr1_lastbwr](转)
  12. PostgreSQL(1)数据库安装(win和linux)
  13. 【SEW-伺服电机-Profinet-io通讯控制——伺服配置】
  14. java 请求webservice_JAVA调用WebService实例
  15. 马哥linux多道处理程序,马哥linux课堂笔记
  16. 日系PC厂商为问题希捷硬盘提供固件更新
  17. 《一课经济学》六、政府价格管制
  18. C语言编程 5.7 从键盘中输入一个英文字母,如果它是大写则转化为小写。如果它是小写则转化为大写,并将其ASCll码显示到屏幕上。
  19. 运行maven打包的项目jar包
  20. ThinkPHP 5.0常用助手函数

热门文章

  1. SourceAnalysis/Binder源码分析.md
  2. WPF中实现图片文件转换成Visual对象,Viewport3D对象转换成图片
  3. 转载 网络上的8051 free IP core资源
  4. Yii 2.0 权威指南 (8) 配合数据库使用
  5. leetcode探索队列和栈(一)
  6. java图形化元件竖直排列_Java:图形化比较排序
  7. ubuntu 打开ssh登陆_Ubuntu开启SSH远程登录
  8. gpu opencl 向量加_【Embedding】GloVe:大规模语料中快速训练词向量
  9. ROS踩坑日记(2)----ERROR: cannot download default sources list from:
  10. linux用户一个用户只能一个用户组,为什么linux用户可以属于多个用户组,文件只能属于一个用户组?...