1.xml文件解析流程解析(一)里面说到在XMLConfigBuilder类中的parseConfiguration方法中来初始化整个Configuration对象,其中XMLConfigBuilder解析Mapper是在此方法的如下代码开始的。
this.mapperElement(root.evalNode("mappers"));
2.XMLConfigBuilder类的mapperElement方法,通过mappers节点下配置的mapper等节点,并通过resourse的值,进行解析*Mapper.xml文件
<mappers>
<mapper resource="mapper/CompanyMapper.xml"/>
<mapper resource="mapper/WareHouseMapper.xml"/>
<mapper resource="mapper/ConsignmentInfoMapper.xml"/>
<mapper resource="mapper/CanvassingInfoMapper.xml"/>
</mappers>
private void mapperElement(XNode parent) throws Exception {
if(parent != null) {
Iterator i$ = parent.getChildren().iterator();
while(true) {
//遍历所有的mapper节点
while(i$.hasNext()) {
XNode child = (XNode)i$.next();
String resource;
if("package".equals(child.getName())) {
resource = child.getStringAttribute("name");
this.configuration.addMappers(resource);
} else {
resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
XMLMapperBuilder mapperParser;
InputStream mapperInterface1;
if(resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
mapperInterface1 = Resources.getResourceAsStream(resource);
mapperParser = new XMLMapperBuilder(mapperInterface1, this.configuration, resource, this.configuration.getSqlFragments());
mapperParser.parse();
} else if(resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
mapperInterface1 = Resources.getUrlAsStream(url);
mapperParser = new XMLMapperBuilder(mapperInterface1, this.configuration, url, this.configuration.getSqlFragments());
mapperParser.parse();
} else {
if(resource != null || url != null || mapperClass == null) {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
Class mapperInterface = Resources.classForName(mapperClass);
this.configuration.addMapper(mapperInterface);
}
}
}
return;
}
}
}
4.XMLMapperBuilder
上面代码中此处为获取resource并通过XMLMapperBuilder来解析文件流。
if(resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
mapperInterface1 = Resources.getResourceAsStream(resource);
mapperParser = new XMLMapperBuilder(mapperInterface1, this.configuration, resource, this.configuration.getSqlFragments());
mapperParser.parse();
}
5.XMLMapperBuilder解析mapper配置文件。
public void parse() {
if(!this.configuration.isResourceLoaded(this.resource)) {
this.configurationElement(this.parser.evalNode("/mapper"));
this.configuration.addLoadedResource(this.resource);
this.bindMapperForNamespace();
}
this.parsePendingResultMaps();
this.parsePendingChacheRefs();
this.parsePendingStatements();
}
6.XMLMapperBuilder的configurationElement是真正mapper节点解析入口,包括sql解析,缓存,等。
private void configurationElement(XNode context) {
try {
String e = context.getStringAttribute("namespace");
if(e.equals("")) {
throw new BuilderException("Mapper\'s namespace cannot be empty");
} else {
//二级缓存相关
this.builderAssistant.setCurrentNamespace(e);
this.cacheRefElement(context.evalNode("cache-ref"));
this.cacheElement(context.evalNode("cache"));
//解析parameterMap
this.parameterMapElement(context.evalNodes("/mapper/parameterMap"));
//解析resultMap
this.resultMapElements(context.evalNodes("/mapper/resultMap"));
//解析sql节点
this.sqlElement(context.evalNodes("/mapper/sql"));
//解析 sql语句
this.buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
}
} catch (Exception var3) {
throw new BuilderException("Error parsing Mapper XML. Cause: " + var3, var3);
}
}
7.总结:
XMLConfigBuilder负责对Mybatis的config文件进行解析入口
而Mapper文件的解析是交给XMLMapperBuilder进行解析的。