本章主要描述 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[]) 方法源码如下:

  1. public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
  2. return getResourceAsStream(resource, getClassLoaders(classLoader));
  3. }
  4. // 该方法返回ClassLoader[]数组,该数组指明了类加载器的使用顺序
  5. ClassLoader[] getClassLoaders(ClassLoader classLoader) {
  6. return new ClassLoader[]{
  7. classLoader,// 参数指定的类加载器
  8. defaultClassLoader,// 类中指定的默认类加载器
  9. Thread.currentThread().getContextClassLoader(),// 当前线程绑定的类加载器
  10. getClass().getClassLoader(),// 加载当前类所使用的类加载器
  11. systemClassLoader};// 系统类加载器
  12. }
  13. InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
  14. // 遍历ClassLoader数组
  15. for (ClassLoader cl : classLoader) {
  16. if (null != cl) {
  17. // 调用ClassLoader.getResourceAsStream方法加载指定的资源
  18. InputStream returnValue = cl.getResourceAsStream(resource);
  19. // 尝试以“/”开头,再次查找
  20. if (null == returnValue) {
  21. returnValue = cl.getResourceAsStream("/" + resource);
  22. }
  23. if (null != returnValue) {
  24. return returnValue;
  25. }
  26. }
  27. }
  28. return null;
  29. }

getResourceAsStream() 方法本质还是使用 Java 类加载器的方式加载配置文件。

Java 加载配置文件的三种方式

项目结构是普通的 Java 项目,非 Maven 项目。如果是 Maven 项目,配置文件会放在 resources 目录下,打成 jar 文件后,配置文件会存在 classpath 根目录下,所以一般使用类加载器的方式加载配置文件。

以下内容转载自:《Java中加载配置文件的三种方式》

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

image.png

1. 通过文件路径加载

  1. /**
  2. * 通过文件路径加载
  3. *
  4. * @throws Exception
  5. */
  6. public static void loadByFilePath() {
  7. InputStream in = null;
  8. try {
  9. in = new FileInputStream(
  10. "E:/project/test/src/com/resource/config.properties");
  11. Properties props = new Properties();
  12. props.load(in);
  13. String host = props.getProperty("host");
  14. System.out.println(host);
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. } finally {
  18. if (in != null) {
  19. try {
  20. in.close();
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }
  26. }

FileInputStream 中的参数是配置文件的真实路径。

2. 通过的 Class 的 getResourceAsStream 进行加载

采用相对路径的方式:
**

  1. /**
  2. * 通过的 Class 的 getResourceAsStream 进行加载,相对路径
  3. */
  4. public static void loadByClassRelativePath() {
  5. InputStream in = null;
  6. try {
  7. in = ResourceLoader.class.getResourceAsStream("config.properties");
  8. Properties props = new Properties();
  9. props.load(in);
  10. String host = props.getProperty("host");
  11. System.out.println(host);
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. } finally {
  15. if (in != null) {
  16. try {
  17. in.close();
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }
  23. }

采用绝对路径的方式:

  1. /**
  2. * 通过的 Class 的 getResourceAsStream 进行加载,绝对路径
  3. */
  4. public static void loadByClassAbsolutePath() {
  5. InputStream in = null;
  6. try {
  7. in = ResourceLoader.class.getResourceAsStream("/com/resource/config.properties");
  8. Properties props = new Properties();
  9. props.load(in);
  10. String host = props.getProperty("host");
  11. System.out.println(host);
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. } finally {
  15. if (in != null) {
  16. try {
  17. in.close();
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }
  23. }

3. 通过类加载器的方式进行加载

  1. /**
  2. * 通过类加载器的方式进行加载
  3. */
  4. public static void loadByClassLoader() {
  5. InputStream in = null;
  6. try {
  7. // ClassLoader会在classpath所在的根目录下查找文件
  8. // 注意:目录最前面不要加 /
  9. in = ResourceLoader.class.getClassLoader().getResourceAsStream("com/resource/config.properties");
  10. Properties props = new Properties();
  11. props.load(in);
  12. String host = props.getProperty("host");
  13. System.out.println(host);
  14. } catch (Exception e) {
  15. e.printStackTrace();
  16. } finally {
  17. if (in != null) {
  18. try {
  19. in.close();
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }
  25. }

作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/brms22 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。