文档章节

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

强子1985
 强子1985
发布于 2017/04/07 22:49
字数 554
阅读 19
收藏 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

粉丝 871
博文 1055
码字总数 750161
作品 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】深入浅出Mybatis(三)——环境搭建

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

kisscatforever
2017/03/08
0
0
mybatis(三)配置详解之properties与environments

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

LCZ777
2014/12/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring应用学习——AOP

1. AOP 1. AOP:即面向切面编程,采用横向抽取机制,取代了传统的继承体系的重复代码问题,如下图所示,性能监控、日志记录等代码围绕业务逻辑代码,而这部分代码是一个高度重复的代码,也就...

江左煤郎
今天
3
0
eclipse的版本

Eclipse各版本代号一览表 Eclipse的设计思想是:一切皆插件。Eclipse核心很小,其它所有功能都以插件的形式附加于Eclipse核心之上。 Eclipse基本内核包括:图形API(SWT/Jface),Java开发环...

mdoo
今天
1
0
SpringBoot源码:启动过程分析(一)

本文主要分析 SpringBoot 的启动过程。 SpringBoot的版本为:2.1.0 release,最新版本。 一.时序图 还是老套路,先把分析过程的时序图摆出来:时序图-SpringBoot2.10启动分析 二.源码分析 首...

Jacktanger
今天
3
0
小白带你认识netty(二)之netty服务端启动(上)

上一章 中的标准netty启动代码中,ServerBootstrap到底是如何启动的呢?这一章我们来瞅下。 server.group(bossGroup, workGroup);server.channel(NioServerSocketChannel.class).optio...

天空小小
今天
3
0
聊聊storm trident batch的分流与聚合

序 本文主要研究一下storm trident batch的分流与聚合 实例 TridentTopology topology = new TridentTopology(); topology.newStream("spout1", spout) .p......

go4it
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部