Mybatis应用和源码学习-如何通过指定配置文件获取InputStream

如何通过指定配置文件获取InputStream

继上一篇Mybatis应用和源码学习-怎么使用Mybatis代替jdbc操作数据库有说到通过Mybatis代替JDBC来操作数据库,其中有一步是通过给定的配置文件路径来获取这个路径对应的InputStream流的逻辑操作具体代码如下:

String resource = "mybatis.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);

从上面的代码可以看出Mybatis把资源的获取委托给了一个工具类Resources去处理了,下面我们就先来看看这个Resources工具类有哪些属性和行为:

Resources工具类的解析

在这里插入图片描述
从Resources类的属性与行为截图可以看出,该类只有两个常量,一个charset 字符编码,一个个classLoaderWrapper 类加载器,主要就是通过这个对象去加载资源的,其余的都是行为,其中一个默认的构造器这个没什么逻辑处理,还有一个根据指定的字符串获取一个类的行为classForName,其余的都是根据字符或者字节流去获取的方法和方法重载。

Resources.getResourceAsStream(resource)方法解析
/**
   * Returns a resource on the classpath as a Stream object
   * 根据classpath路劲下的路径,返回classpath路径下的InputStream对象
   *
   * @param resource The resource to find 根据这个路径去找InputStream流
   * @return The resource 返回InputStream流
   * @throws java.io.IOException If the resource cannot be found or read 如果这个InputStream对象没有找到就抛出io异常
   */
  public static InputStream getResourceAsStream(String resource) throws IOException {
    return getResourceAsStream(null, resource);
  }

该方法被调用后方法体没有执行特殊操作,只是执行了下面自己的一个重载方法,把主要逻辑都委托给重载方法去执行了。

/**
   * Returns a resource on the classpath as a Stream object
   *根据classpath路劲下的路径,返回classpath路径下的InputStream对象
   *
   * @param loader   The classloader used to fetch the resource  这个classloader 用来寻找InputStream对象
   * @param resource The resource to find 根据这个路径去找InputStream流
   * @return The resource 返回InputStream流
   * @throws java.io.IOException If the resource cannot be found or read 如果这个InputStream对象没有找到就抛出io异常
   */
  public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
    InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
    if (in == null) {
      throw new IOException("Could not find resource " + resource);
    }
    return in;
  }

这里主要处理逻辑就是通过Resources类的classLoaderWrapper的getResourceAsStream方法去获取资源,如果获取到了InputStream资源就返回该对象,如果没有获取到该对象就抛出一个IO异常,并给出信息,没有找到给定的路径的资源对象,
下面看下classLoaderWrapper的getResourceAsStream方法处理了啥

/**
   * Get a resource from the classpath, starting with a specific class loader
   * 根据指定的classloader 获得在classpath路径下的 InputStream 对象
   * @param resource    - the resource to find 根据这个路径去找InputStream流
   * @param classLoader - the first class loader to try
   * @return the stream or null
   */
  public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
    return getResourceAsStream(resource, getClassLoaders(classLoader));
  }

这个方法跟Resources类的逻辑差不多都是执行自己的重载方法,不过这个方法的参数会先去获取一下用来加载资源的类加载器,然后再执行自己的重载方法,
先看下getClassLoader()这个获取类加载器的方法逻辑:

ClassLoader[] getClassLoaders(ClassLoader classLoader) {
    return new ClassLoader[]{
        classLoader,
        defaultClassLoader,
        Thread.currentThread().getContextClassLoader(),
        getClass().getClassLoader(),
        systemClassLoader};
  }

这个方法其实就是返回了一个ClassLoader数组,但是其中5个对象,通常情况都是使用了Thread.currentThread().getContextClassLoader()这个获取当前线程的上下文的类加载器,上述方法也是使用的这个
下面接着看下getResourceAsStream 的重载方法逻辑

/**
   * Try to get a resource from a group of classloaders
   *
   * @param resource    - the resource to get
   * @param classLoader - the classloaders to examine
   * @return the resource or null
   */
  InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
    for (ClassLoader cl : classLoader) {
      if (null != cl) {

        // try to find the resource as passed
        //尽力 使用java的ClassLoader类的资源获取方法 去查找资源对象
        InputStream returnValue = cl.getResourceAsStream(resource);

        // now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource
        //如果上一步没有查询到资源对象,那么在这里会给资源路径添加一个“/”字符,再尝试一次查询
        if (null == returnValue) {
          returnValue = cl.getResourceAsStream("/" + resource);
        }

        if (null != returnValue) {
          return returnValue;
        }
      }
    }
    return null;
  }

该方法的逻辑就是通过获取的classLoader类加载器来操作数据,如果累加器都为空就直接返回null,因为没有可用的类加载器,如果不为空,就调用JAVA的类ClassLoader对应的API获取资源,这个获取资源的动作就委托给JAVA的API去处理了,资源这个JAVA API是怎么获取的这里不去深究处理过程,比较繁琐,咱们只要会使用这个API去调用就行了。如果通过API获取到了InputStream资源就返回这个资源对象,如果没有获取到会再该资源路径的前面加一个“/”字符再执行一次API,尝试再次获取该资源,如果获取到就返回该对象,获取不到就返回NULL.
至此,Mybatis通过Resources的getResourceAsStream方法根据给定的资源路径获取该路径对应的InputStream对象的代码逻辑就结束了。

最后看下Resources获取资源的时许图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值