MyBatis框架的使用及源码分析(六) MapperRegistry
我们先Mapper接口的调用方式,见<MyBatis框架中Mapper映射配置的使用及原理解析(一) 配置与使用>的示例:
public void findUserById() {
SqlSessionFactory sqlSessionFactory = getSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectByPrimaryKey(1l);
System.out.println(user.getId() + " / " + user.getName());
}
sqlsession.getMapper(UserMapper.class) 也就是调用DefaultSqlSession的对应方法:
public <T> T getMapper(Class<T> type) {
return configuration.<T>getMapper(type, this);
}
继续跟踪Configuration对象对应源码:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
我们在回忆,在 <MyBatis框架中Mapper映射配置的使用及原理解析(四) 解析Mapper接口映射xml文件> 一文,我们知道在读取mapper xml文件后会调用org.apache.ibatis.builder.xml.XMLMapperBuilder类的bindMapperForNamespace()方法,绑定到命名空间:
private void bindMapperForNamespace() {
String namespace = builderAssistant.getCurrentNamespace();
if (namespace != null) {
Class<?> boundType = null;
try {
boundType = Resources.classForName(namespace);
} catch (ClassNotFoundException e) {
//ignore, bound type is not required
}
if (boundType != null) {
if (!configuration.hasMapper(boundType)) {//判断是否存在
// Spring may not know the real resource name so we set a flag
// to prevent loading again this resource from the mapper interface
// look at MapperAnnotationBuilder#loadXmlResource
configuration.addLoadedResource("namespace:" + namespace);//添加资源标识
configuration.addMapper(boundType); //Mapper接口添加到Configuration
}
}
}
}
继续跟踪configuration.addMapper(boundType)方法:
public <T> void addMapper(Class<T> type) {
mapperRegistry.addMapper(type);
}
我们发现添加和获取Mapper实例都使用到了同一个类MapperRegistry,在Configuration中的声明如下:
protected MapperRegistry mapperRegistry = new MapperRegistry(this);
下面贴出MapperRegistry的源代码:
package org.apache.ibatis.binding; import org.apache.ibatis.builder.annotation.MapperAnnotationBuilder;
import org.apache.ibatis.io.ResolverUtil;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession; import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set; public class MapperRegistry { private Configuration config;
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>(); public MapperRegistry(Configuration config) {
this.config = config;
} @SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null)
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
} public <T> boolean hasMapper(Class<T> type) {
return knownMappers.containsKey(type);
} public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
knownMappers.put(type, new MapperProxyFactory<T>(type));
// It's important that the type is added before the parser is run
// otherwise the binding may automatically be attempted by the
// mapper parser. If the type is already known, it won't try.
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
knownMappers.remove(type);
}
}
}
} /**
* @since 3.2.2
*/
public Collection<Class<?>> getMappers() {
return Collections.unmodifiableCollection(knownMappers.keySet());
} /**
* @since 3.2.2
*/
public void addMappers(String packageName, Class<?> superType) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
for (Class<?> mapperClass : mapperSet) {
addMapper(mapperClass);
}
} /**
* @since 3.2.2
*/
public void addMappers(String packageName) {
addMappers(packageName, Object.class);
} }
我们清楚的看到注册Mapper和获取Mapper都是在一个Map对象中存取Mapper的代理对象MapperProxyFactory。
经过这篇文章,我们清楚的知道了MapperRegistry的功能就是注册和获取Mapper对象的代理。
MyBatis框架的使用及源码分析(六) MapperRegistry的更多相关文章
- MyBatis框架的使用及源码分析(十一) StatementHandler
我们回忆一下<MyBatis框架的使用及源码分析(十) CacheExecutor,SimpleExecutor,BatchExecutor ,ReuseExecutor> , 这4个Ex ...
- MyBatis框架的使用及源码分析(九) Executor
从<MyBatis框架的使用及源码分析(八) MapperMethod>文中我们知道执行Mapper的每一个接口方法,最后调用的是MapperMethod.execute方法.而当执行Ma ...
- MyBatis框架的使用及源码分析(八) MapperMethod
从 <MyBatis框架中Mapper映射配置的使用及原理解析(七) MapperProxy,MapperProxyFactory> 文中,我们知道Mapper,通过MapperProxy ...
- MyBatis框架的使用及源码分析(五) DefaultSqlSessionFactory和DefaultSqlSession
我们回顾<MyBatis框架中Mapper映射配置的使用及原理解析(一) 配置与使用> 一文的示例 private static SqlSessionFactory getSessionF ...
- MyBatis框架的使用及源码分析(四) 解析Mapper接口映射xml文件
在<MyBatis框架中Mapper映射配置的使用及原理解析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder> 一文中,我们知道mybat ...
- MyBatis框架的使用及源码分析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder
在 <MyBatis框架中Mapper映射配置的使用及原理解析(一) 配置与使用> 的demo中看到了SessionFactory的创建过程: SqlSessionFactory sess ...
- MyBatis框架的使用及源码分析(十) CacheExecutor,SimpleExecutor,BatchExecutor ,ReuseExecutor
Executor分成两大类,一类是CacheExecutor,另一类是普通Executor. 普通类又分为: ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情.它为每个语句的执行 ...
- MyBatis框架的使用及源码分析(七) MapperProxy,MapperProxyFactory
从上文<MyBatis框架中Mapper映射配置的使用及原理解析(六) MapperRegistry> 中我们知道DefaultSqlSession的getMapper方法,最后是通过Ma ...
- MyBatis框架的使用及源码分析(三) 配置篇 Configuration
从上文<MyBatis框架中Mapper映射配置的使用及原理解析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder> 我们知道XMLConf ...
随机推荐
- 欢迎来怼--第二十一次Scrum会议
一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华 小组照片 二.开会信息 时间:2017/11/2 17:05~17:15,总计10min. 地点: ...
- Thunder团队第三周 - Scrum会议1
Scrum会议1 小组名称:Thunder 项目名称:i阅app Scrum Master:王航 工作照片: 杨梓瑞在拍照,所以不在照片中. 参会成员: 王航(Master):http://www.c ...
- Android UI 设计之 TextView EditText 组件属性方法最详细解析
. 作者 :万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . TextView 相关类的继承结构 ...
- 共享程序集GAC
原文标题: 原文地址:https://www.cnblogs.com/1996V/p/9037603.html 共享程序集GAC 我上面说了这么多有关CLR加载程序集的细节和规则,事实上,类似于msc ...
- Spring学习(二)—— java的动态代理机制
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- JS 书籍拓展内容
一.面向对象
- Windows Server 2012四大版本介绍
今天刚好要尝试安装Windows Server 2012,在网上百度了下发现有4个版本,分别是: Datacenter数据中心版. Standard标准版. Essentials版. Foundati ...
- (转)centos6.5下Zabbix系列之Zabbix安装搭建及汉化
最近在研究zabbix,在整理完成之后就有了写一下总结博客的想法,在我研究zabbix的时候给我很大帮助的是it你好,博客地址 http://itnihao.blog.51cto.com/他做的zab ...
- C#窗口文件双击打开时出错
出错原因: 1. 修改了该窗口文件的.Designer.cs文件中:#region Windows 窗体设计器生成的代码这里面的代码,导致运行不正常. 为了传递数据,我在构造函数中增加了传递的值. 需 ...
- string字符串比较和替换
我用的是小写的string!! #include <string> #include <iostream> using namespace std; int main() { ...