文章目录
MapperStatement注册过程
MapperStatement注册时序
MapperStatement的注册过程发生在Mybatis启动时构造Configuration对象的时候,XMLConfigBuilder对象的mapperElement方法负责解析Mapper文件并进行注册。
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
loadCustomLogImpl(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
// 解析Mapper文件并注册
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
XMLConfigBuilder的mapperElement方法
首先来看一下Mapper文件配置的几种方式。
<mappers>
<!-- 通过resource属性指定Mapper文件的classpath路径 -->
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<!-- 通过urll属性指定Mapper文件网络路径 -->
<mapper url="file://var/mappers/BlogMapper.xml"/>
<!-- 通过class属性指定Mapper接口的完全限定名 -->
<mapper class="org.mybatis.builder.PostMapper"/>
<!-- 通过package标签指定Mapper接口所在的包名 -->
<package name="org.mybatis.builder"/>
</mappers>
mapperElement分四种情况进行Mapper文件的注册,通过扫描包路径下的Mapper接口最后注册注解类型的Mapper文件,注册classpath下的Mapper文件,注册远程url指定的Mapper文件,注册注解类型的Mapper文件。
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
// 通过package标签指定Mapper接口所在的包名
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");
// 读取classpath下的mapper文件
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url != null && mapperClass == null) {
// 读取远程url的mapper文件
ErrorContext.instance().resource(url);
InputStream inputStream = Resources.getUrlAsStream(url);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url == null