Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 - 推酷 - 360安全浏览器 7.1
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客
时间 2014-02-11 21:08:00 博客园-所有随笔区原文 http://www.cnblogs.com/daxin/p/3545040.html
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类的源码 看看是如何自动扫描的。
1 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 @Override
2 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 }
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类的源码 看看是如何自动扫描的。
1 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 @Override
2 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 }
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 - 推酷 - 360安全浏览器 7.1的更多相关文章
- Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring 非原创[只为记录],原博文地址:https://www.cnblogs.com/ ...
- (转)Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring Mybatis在与Spring集成的时候可以配置MapperFactoryBea ...
- MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring
Mybatis在与Spring集成的时候可以配置 MapperFactoryBean来生成Mapper接口的代理. 例如 <bean id="userMapper" clas ...
- Mybaits 源码解析 (十一)----- 设计模式精妙使用:静态代理和动态代理结合使用:@MapperScan将Mapper接口生成代理注入到Spring
上一篇文章我们讲了SqlSessionFactoryBean,通过这个FactoryBean创建SqlSessionFactory并注册进Spring容器,这篇文章我们就讲剩下的部分,通过Mapper ...
- mybatis如何根据mapper接口生成其实现类
SpringBoot集成mybatis mybatis的statement的解析与加载 mybatis如何根据mapper接口生成其实现类 mybatis的mapper返回map结果集 mybatis ...
- Mybatis学习系列(四)Mapper接口动态代理
实现原理及规范 Mapper接口动态代理的方式需要手动编写Mapper接口,Mybatis框架将根据接口定义创建接口的动态代理对象,代理对象的方法体实现Mapper接口中定义的方法. 使用Mapper ...
- IntelliJ IDEA中Mapper接口通过@Autowired注入报错的正确解决方式
转载请注明来源:四个空格 » IntelliJ IDEA中Mapper接口通过@Autowired注入报错的正确解决方式: 环境 ideaIU-2018.3.4.win: 错误提示: Could no ...
- python编写的自动获取代理IP列表的爬虫-chinaboywg-ChinaUnix博客
python编写的自动获取代理IP列表的爬虫-chinaboywg-ChinaUnix博客 undefined Python多线程抓取代理服务器 | Linux运维笔记 undefined java如 ...
- mybatis如何根据mapper接口生成其实现类(springboot)
序 mybatis里头给sqlSession指定执行哪条sql的时候,有两种方式,一种是写mapper的xml的namespace+statementId,如下: public Student fin ...
随机推荐
- django自关联,auth模块
一.自关联 写蛮好的一篇博客:https://www.cnblogs.com/Kingfan1993/p/9936541.html 1.一对多关联 1.表内自关联是指表内数据相关联的对象和表是相同字段 ...
- Django-debug-toolbar(调试使用)
Django-debug-toolbar django-debug-toolbar 是一组可配置的面板,可显示有关当前请求/响应的各种调试信息,并在单击时显示有关面板内容的更多详细信息. https: ...
- 攻防世界(XCTF)WEB(进阶区)write up(一)
cat ics-05 ics-06 lottery Cat XCTF 4th-WHCTF-2017 输入域名 输入普通域名无果 输入127.0.0.1返回了ping码的结果 有可能是命令执行 ...
- CDN实现原理
避让:尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快.更稳定. 检测:通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时监 ...
- [CODEVS6333] (数据加强)特种部队
题目描述 Description 某特种部队接到一个任务,需要潜入一个仓库.该部队士兵分为两路,第一路士兵已经在正面牵制住了敌人,第二路士兵正在悄悄地从后方秘密潜入敌人的仓库.当他们到达仓库时候,发现 ...
- WCF 入门调用实例教程
WCF的相关概念信息就不在此赘述了,网上一搜一大把. 现在让我们动手搭建我们的第一个wcf程序吧,具体流程如下: 1. 新建立空白解决方案,并在解决方案中新建项目,项目类型为:WCF服务应用程序. 2 ...
- LeetCode初级算法--动态规划01:爬楼梯
LeetCode初级算法--动态规划01:爬楼梯 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net ...
- jmeter打印变量的三种方式
1.使用Debug Sampler 2.使用log打印到jemter日志 3.使用System.out.println打印到cmd命令行
- python中生成器与迭代器
可迭代对象:一个实现了iter方法的对象是可迭代的 迭代器:一个实现了iter方法和next方法的对象就是迭代器 生成器都是Iterator对象,但list.dict.str虽然是Iterable(可 ...
- 5. Sersync实时同步
rsync+Sersync数据的实时同步 sersync介绍 1.什么是实时同步 监控一个目录的变化, 当该目录触发事件(创建\删除\修改) 就执行动作, 这个动作可以是 rsync同步 ,也可以是其 ...