本章主要描述 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中加載配置文件的三種方式》
配置文件放置位置如下圖所示:
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 源碼篇