MyBatis 源碼篇-資源加載

本章主要描述 MyBatis 資源加載模塊中的 ClassLoaderWrapper 類和 Java 加載配置文件的三種方式。

ClassLoaderWrapper

上一章的案例,使用 org.apache.ibatis.io.Resources#getResourceAsStream(java.lang.String) 方法加載 MyBatis 的配置文件。Resources 是一個提供了多個靜態方法的工具類,內部封裝了 ClassLoaderWrapper 類的靜態字段,Resources 提供的方法都是在 ClassLoaderWrapper 對象中實現的。

ClassLoaderWrapper 主要提供了三類方法:classForName() 方法、getResourceAsStream() 方法、getResourceAsURL() 方法,這三個方法都有多個重載。這裏以 getResourceAsStream() 方法爲例進行介紹。

org.apache.ibatis.io.ClassLoaderWrapper#getResourceAsStream(java.lang.String, java.lang.ClassLoader[]) 方法源碼如下:

public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
  return getResourceAsStream(resource, getClassLoaders(classLoader));
}

// 該方法返回ClassLoader[]數組,該數組指明瞭類加載器的使用順序
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
  return new ClassLoader[]{
      classLoader,// 參數指定的類加載器
      defaultClassLoader,// 類中指定的默認類加載器
      Thread.currentThread().getContextClassLoader(),// 當前線程綁定的類加載器
      getClass().getClassLoader(),// 加載當前類所使用的類加載器
      systemClassLoader};// 系統類加載器
}

InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
  // 遍歷ClassLoader數組
  for (ClassLoader cl : classLoader) {
    if (null != cl) {
      // 調用ClassLoader.getResourceAsStream方法加載指定的資源
      InputStream returnValue = cl.getResourceAsStream(resource);
      // 嘗試以“/”開頭,再次查找
      if (null == returnValue) {
        returnValue = cl.getResourceAsStream("/" + resource);
      }
      if (null != returnValue) {
        return returnValue;
      }
    }
  }
  return null;
}

getResourceAsStream() 方法本質還是使用 Java 類加載器的方式加載配置文件。

Java 加載配置文件的三種方式

項目結構是普通的 Java 項目,非 Maven 項目。如果是 Maven 項目,配置文件會放在 resources 目錄下,打成 jar 文件後,配置文件會存在 classpath 根目錄下,所以一般使用類加載器的方式加載配置文件。

以下內容轉載自:《Java中加載配置文件的三種方式》

配置文件放置位置如下圖所示:

image.png

1. 通過文件路徑加載

/**
 * 通過文件路徑加載
 *
 * @throws Exception
 */
public static void loadByFilePath() {
    InputStream in = null;
    try {
        in = new FileInputStream(
                "E:/project/test/src/com/resource/config.properties");
        Properties props = new Properties();
        props.load(in);
        String host = props.getProperty("host");
        System.out.println(host);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

FileInputStream 中的參數是配置文件的真實路徑。

2. 通過的 Class 的 getResourceAsStream 進行加載

採用相對路徑的方式:

/**
 * 通過的 Class 的 getResourceAsStream 進行加載,相對路徑
 */
public static void loadByClassRelativePath() {
    InputStream in = null;
    try {
        in = ResourceLoader.class.getResourceAsStream("config.properties");
        Properties props = new Properties();
        props.load(in);
        String host = props.getProperty("host");
        System.out.println(host);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

採用絕對路徑的方式:

/**
 * 通過的 Class 的 getResourceAsStream 進行加載,絕對路徑
 */
public static void loadByClassAbsolutePath() {
    InputStream in = null;
    try {
        in = ResourceLoader.class.getResourceAsStream("/com/resource/config.properties");
        Properties props = new Properties();
        props.load(in);
        String host = props.getProperty("host");
        System.out.println(host);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3. 通過類加載器的方式進行加載

/**
 * 通過類加載器的方式進行加載
 */
public static void loadByClassLoader() {
    InputStream in = null;
    try {
        // ClassLoader會在classpath所在的根目錄下查找文件
        // 注意:目錄最前面不要加 /
        in = ResourceLoader.class.getClassLoader().getResourceAsStream("com/resource/config.properties");
        Properties props = new Properties();
        props.load(in);
        String host = props.getProperty("host");
        System.out.println(host);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

MyBatis 源碼篇

 

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