MyBatis源碼的學習(9)---映射器mappers的的XML解析

來自官方文檔

解析的方式如下:

<!-- 使用相對於類路徑的資源引用 -->
<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)

類加載器加載資源的時候,先用不帶“/”的相對路徑的方式加載,這種方式,要求我們的加載類(接口和類對於類加載器來說一樣)和文件是放到一起的。

使用“/”這種的時候,相對的是項目的跟路徑,就是從跟路徑開始找。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章