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

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

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

转载于:https://my.oschina.net/qiangzigege/blog/875117

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值