來自官方文檔
解析的方式如下:
<!-- 使用相對於類路徑的資源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定資源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口實現類的完全限定類名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 將包內的映射器接口實現全部註冊爲映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
//XMLConfigBuilder類的如下方法
/**
<mappers>
<!--這是告訴Mybatis區哪找持久化類的映射文件,對於在src下的文件直接寫文件名,
如果在某包下,則要寫明路徑,如:com/mybatistest/config/User.xml-->
<mapper resource="userMapper.xml"></mapper>
</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);
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);
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.");
}
}
}
}
}
先分一下類:package與class這是一組;url和resource是一組
最終都會調用的方法:使用XMLMapperBuilder類中的parse()進行解析
使用的如果是:package和class時,都會將類似 com.org.learn.UserMapper 這樣的全限定類名,轉換爲我們的路徑格式:
com/org/learn/UserMapper.xml。
package:對應的是多個class的集合
看上面的註釋:使用class和package這一類的方式,主要是爲了集成Spring。另外,需要注意的是,使用這一類方式時,xml文件的名稱一定要和接口名一樣。(UserMapper接口對應UserMapper.xml)
然後,我們看我們的資源文件UserMapper.xml的讀取
第一種:類似於 /com/org/learn/UserMapper.xml (先使用相對路徑,如果沒有使用類加載器加載)
第二種:類加載器加載 com/org/learn/UserMapper.xml
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
return new ClassLoader[]{
classLoader,
defaultClassLoader,
Thread.currentThread().getContextClassLoader(),
getClass().getClassLoader(),
systemClassLoader};
}
一共有五個類加載器,挨個進行資源的讀取。
如果,想要具體的測試每一種加載xml的方式:
我們無需自己再編寫測試用例,直接在源碼中的test找,關於這個類XMLMapperBuilder 的單元測試用例
不管是哪種方式的,加載資源。最終都會調用到我們上面的那個方法:
getResourceAsStream(String resource, ClassLoader[] classLoader)
類加載器加載資源的時候,先用不帶“/”的相對路徑的方式加載,這種方式,要求我們的加載類(接口和類對於類加載器來說一樣)和文件是放到一起的。
使用“/”這種的時候,相對的是項目的跟路徑,就是從跟路徑開始找。