• 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 源码篇

  • 相关阅读:
    JavaScript中判断函数是new还是()调用
    IE6/7 and IE8/9(Q)中td的上下padding失效
    JQuery中html()方法使用不当带来的陷阱
    有name为action的表单元素时取form的属性action杯具了
    为非IE浏览器添加mouseenter,mouseleave事件
    各浏览器中querySelector和querySelectorAll的实现差异
    仅IE6/7/8中innerHTML返回值忽略英文空格
    各浏览器关键字/保留字作为对象属性的差异
    各浏览器中鼠标按键值的差异
    给body标签和document.body都添加点击事件后仅Firefox弹出了两次
  • 原文地址:https://www.cnblogs.com/yinjw/p/11757421.html
Copyright © 2020-2023  润新知