【mybatis源码解析】(一)mybatis执行流程以及实现原理
【mybatis源码解析】(二)详解mybatis中java动态代理模式的运用
【mybatis源码解析】(三)MapperRegistry类解析
系列文章目录前言一、MapperRegistry是什么?二、MapperRegistry初始化
前言
前面两篇文章介绍了大体流程,这篇着重介绍跟MapperRegistry相关的类
一、MapperRegistry是什么?MapperRegistry翻译过来就是映射器注册表
看看他的属性
config是存储了mybatis相关配置的类
knownMappers是一个以mpper接口类对象为key,MapperProxyFactory为值的map集合
构造函数需要传入配置对象
getMapper方法返回mapper的动态代理生成的对象
配置中是否拥有mapper
添加一个MapperFProxyFactory对象到map集合,初始化时候会调用
在Configuration类中我们可以看到MapperRegistry的属性创建,说明在创建Configuration类时候就创建了MapperRegistry对象。
Configuration类在XMLConfigBuilder类中完成了创建
接下来看看的XMLConfigBuilder的parseConfiguration(XNode root)方法
有一个mapperElement(root.evalNode(“mappers”));方法,进去看看
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String mapperPackage = child.getStringAttribute("name");
configuration.addMappers(mapperPackage);
} else {
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
try(InputStream inputStream = Resources.getResourceAsStream(resource)) {
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();
}
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
try(InputStream inputStream = Resources.getUrlAsStream(url)){
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
}
} else if (resource == null && url == null && mapperClass != null) {
Class> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
}
}
}
}
处理方法总结来说就是解析xml配置,将mapper相关信息提出来,调用configuration.addMappers(mapperPackage),将mapper加入MapperRegistry的knownMappers属性
就是这个方法
publicvoid addMapper(Class 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<>(type));//创建MapperProxyFactory工厂类放入 // 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);//mapper其他配置解析生成 parser.parse(); loadCompleted = true; } finally { if (!loadCompleted) { knownMappers.remove(type); } } } }



