文档章节

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

强子1985
 强子1985
发布于 2017/04/07 22:49
字数 554
阅读 17
收藏 1

之前调试时,发现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();
	}

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

© 著作权归作者所有

共有 人打赏支持
强子1985

强子1985

粉丝 862
博文 943
码字总数 648753
作品 8
南京
架构师
mybatis核心组件详解——MapperAnnotationBuilder

MapperAnnotationBuilder(org.apache.ibatis.builder.annotation.MapperAnnotationBuilder),mapper注解构建器。 它的职责很简单,就是解析指定的mapper接口对应的Class对象中,包含的所有...

拉风小野驴
2016/02/29
472
2
MyBatis整合Spring的实现(17)

这里也只使用一个例子来分析 1 方法bindMapperForNamespace private void bindMapperForNamespace() { // cn.vansky.schedule.time.menu.dao.MenuMapper String namespace = builderAssista......

tara_qri
2015/10/30
0
0
【深入浅出MyBatis系列三】Mapper映射文件配置

深入浅出MyBatis系列 【深入浅出MyBatis系列一】MyBatis入门 【深入浅出MyBatis系列二】配置简介(MyBatis源码篇) 【深入浅出MyBatis系列三】Mapper映射文件配置 【深入浅出MyBatis系列四】...

陶邦仁
2015/12/22
2.2K
1
mybatis(三)配置详解之properties与environments

上一篇我们通过对mybatis源码的简单分析,可看出,在mybatis配置文件中,在configuration根节点下面,可配置properties、typeAliases、plugins、objectFactory、objectWrapperFactory、setti...

LCZ777
2014/12/18
0
0
【Mybatis】深入浅出Mybatis(三)——环境搭建

一、前言 前一篇博客向大家介绍了Mybatis的架构——【Mybatis】深入浅出Mybatis(二)——Mybatis的框架,在这篇我们就开始通过一个例子来搭建一下Mybatis的环境。 二、环境要求 mybatis-3....

kisscatforever
2017/03/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

00.编译OpenJDK-8u40的整个过程

前言 历经2天的折腾总算把OpenJDK给编译成功了,要说为啥搞这个,还得从面试说起,最近出去面试经常被问到JVM的相关东西,总感觉自己以前学的太浅薄,所以回来就打算深入学习,目标把《深入理...

凌晨一点
今天
2
0
python: 一些关于元组的碎碎念

初始化元组的时候,尤其是元组里面只有一个元素的时候,会出现一些很蛋疼的情况: def checkContentAndType(obj): print(obj) print(type(obj))if __name__=="__main__": tu...

Oh_really
昨天
6
2
jvm crash分析工具

介绍一款非常好用的jvm crash分析工具,当jvm挂掉时,会产生hs_err_pid.log。里面记录了jvm当时的运行状态以及错误信息,但是内容量比较庞大,不好分析。所以我们要借助工具来帮我们。 Cras...

xpbob
昨天
113
0
Qt编写自定义控件属性设计器

以前做.NET开发中,.NET直接就集成了属性设计器,VS不愧是宇宙第一IDE,你能够想到的都给你封装好了,用起来不要太爽!因为项目需要自从全面转Qt开发已经6年有余,在工业控制领域,有一些应用...

飞扬青云
昨天
4
0
我为什么用GO语言来做区块链?

Go语言现在常常被用来做去中心化系统(decentralised system)。其他类型的公司也都把Go用在产品的核心模块中,并且它在网站开发中也占据了一席之地。 我们在决定做Karachain的时候,考量(b...

HiBlock
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部