文档章节

MyBatis-3.4.2-源码分析17:XML解析之bindMapperForNamespace

强子大叔的码田
 强子大叔的码田
发布于 2017/04/07 22:49
字数 554
阅读 108
收藏 1

精选30+云产品,助力企业轻松上云!>>>

之前调试时,发现1个问题,就是mapperRegistry找不到对象

后来发现是mapper.xml的namespace里面的类名写得不对,然后来重新debug下

---

断点在

stop in org.apache.ibatis.builder.xml.XMLMapperBuilder.bindMapperForNamespace

调试

private void bindMapperForNamespace() {
		// 看到这里了
		String namespace = builderAssistant.getCurrentNamespace();
		System.out.println("namespace--->"+namespace);
		if (namespace != null) {
			// 如果设置了
			Class<?> boundType = null;
			try {
				// 看看是不是类
				boundType = Resources.classForName(namespace);
			} catch (ClassNotFoundException e) {
				// ignore, bound type is not required
			}
			//如果真的是类/接口
			if (boundType != null) {
				System.out.println("boundType--->"+boundType);
				//之前没有绑定
				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);
				}
			}
		}
	}

可以看到,关键就是

configuration.addLoadedResource("namespace:" + namespace);
					configuration.addMapper(boundType);

 跟进去

第1行就是标记这个资源加载过了,见下图

319    		loadedResources.add(resource);

main[1] print loadedResources
 loadedResources = "[mysql_mapper.xml]"
main[1] step
> 
Step completed: "thread=main", org.apache.ibatis.session.Configuration.addLoadedResource(), line=320 bci=11
320    	}

main[1] print loadedResources
 loadedResources = "[mysql_mapper.xml, namespace:interfaces.RoleMapper]"

看第2行

configuration.addMapper(boundType);
public <T> void addMapper(Class<T> type) {
		// 交给mapperRegistry负责
		mapperRegistry.addMapper(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);
				}
			}
		}
	}

这里继续跟踪

knownMappers.put(type, new MapperProxyFactory<T>(type));

/**
 * @author Lasse Voss
 */
public class MapperProxyFactory<T> {
	// 接口类
	private final Class<T> mapperInterface;
	// 方法容器
	private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();

	public MapperProxyFactory(Class<T> mapperInterface) {
		// 设置接口类
		this.mapperInterface = mapperInterface;
		//end
	}

---然后就剩下

MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
                parser.parse();

先看MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);

然后就是parse解析过程了
---

public void parse() {
		// 开始解析
		String resource = type.toString();
		// 如果没有加载过
		if (!configuration.isResourceLoaded(resource)) {
			// 进来
			// 这1行不执行
			loadXmlResource();
			// 标记已经加载过了
			configuration.addLoadedResource(resource);
			//
			assistant.setCurrentNamespace(type.getName());
			// 继续执行
			// 下面2行注释掉
			parseCache();
			parseCacheRef();
			//正式
			//获取类的方法
			Method[] methods = type.getMethods();
			//遍历每1个方法
			for (Method method : methods) {
				//
				try {
					// issue #237
					//如果不是bridge方法
					if (!method.isBridge()) {
						//解析此方法
						parseStatement(method);
					}
				} catch (IncompleteElementException e) {
					configuration.addIncompleteMethod(new MethodResolver(this, method));
				}
			}
		}
		parsePendingMethods();
	}

上面是注解解析的过程,暂且不表。

强子大叔的码田

强子大叔的码田

粉丝 924
博文 1630
码字总数 1283214
作品 9
南京
架构师
私信 提问
加载中
请先登录后再评论。
Mybatis架构设计及源码分析-mapper.xml文件解析

使用mybatis我们通常会自己去书写mapper.xml文件,文件内部通常会书写sql语句相关信息,下面我们将分析mybatis是如何解析这些信息并保存于全部配置类Configuration中。 回到之前的代码mappe...

申文波
2018/05/26
179
0
Mybatis源码分析------Mapper动态代理源码分析

java之路由浅入深,由深入浅。近来,感觉自己什么都会,感觉又什么都不会。所以,在这个过程中针扎着,带着针扎,开始了mybatis的源码分析。本篇为第一篇,后续将陆续更新。第一遍先从Mappe...

峥嵘岁月
2019/01/05
20
0
mybatis 源码分析(一)框架结构概览

本篇博客将主要对 mybatis 整体介绍,包括 mybatis 的项目结构,执行的主要流程,初始化流程,API 等各模块进行简单的串联,让你能够对 mybatis 有一个整体的把握。另外在 mybatis 源码的阅读...

osc_qbe93woo
04/16
4
0
Mybatis 解析 SQL 源码分析一

相关文章 Mybatis 解析配置文件的源码解析 Mybatis 类型转换源码分析 Mybatis 数据源和数据库连接池源码解析(DataSource) Mybatis Mapper 接口源码解析(binding包) Mybatis Mapper.xml 配...

TSMYK
2018/11/11
715
2
mybatis源码解析之加载篇(一)

一、前言乱讲 在使用原生mybatis的每个都写过这样一段代码:

我是只呆呆兽
2019/07/18
1
0

没有更多内容

加载失败,请刷新页面

加载更多

使当前提交成为Git存储库中唯一的(初始)提交? - Make the current commit the only (initial) commit in a Git repository?

问题: I currently have a local Git repository, which I push to a Github repository. 我目前有一个本地Git存储库,我将其推送到Github存储库。 The local repository has ~10 commits, ......

javail
18分钟前
14
0
IntelliJ IDEA 默认快捷键大全

Remember these Shortcuts 常用 功能 快捷键 备注 ● Smart code completion Ctrl + Shift + Space - ● Search everywhere Double Shift - ● Show intention actions and quick-fixes Alt......

巨輪
57分钟前
18
0
Hacker News 简讯 2020-07-14

更新时间: 2020-07-14 01:01 I Know What You Download on BitTorrent - (iknowwhatyoudownload.com) 我知道你在BitTorrent上下载了什么 得分:196 | 评论:159 Show HN: Primo – all-in-one......

FalconChen
今天
129
0
绕过移动端系统限制的 dlopen 库 byOpen

byOpen是一个绕过移动端系统限制的增强版dlfunctions库。 支持特性 Android 支持App中加载和使用Android系统库接口(即使maps中还没有被加载也支持)。 Android 7以上dlopen, System.load都是...

shzwork
昨天
31
0
Golang学习系列第二天:变量、常量、数据类型和流程语句

继golang第一天后,今天学习下golang的变量、常量、数据类型和控制流语句。 做过其他编程语言(比如JavaScript,java,python)项目的话,其实很好理解变量、常量、数据类型和控制流。 变量也...

董广明
昨天
48
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部