02_配置文件读取

系列文章目录


前言


一、为什么大部分的框架都要自己弄一个Resource类呢

我们先从第一行进行分析

  //2.读取配置文件
  reader = Resources.getResourceAsReader(resource);//2.读取配置文件

这个类是读取资源类,具体完成将xml文件加载生成一个Reader,这里我就有一个疑问,为什么大部分的框架都要自己弄一个Resource类呢?加载一个文件或URL资源都是比较简单的?真是这样子吗?我们来看看Resource.class的源代码:

/**
 * A class to simplify access to resources through the classloader.
 *  一个简单的通过类加载器访问资源的类
 *
 * @author Clinton Begin
 */
public class Resources {


  //类加载器包装类?为什么,我们接后面再看
  private static ClassLoaderWrapper classLoaderWrapper = new ClassLoaderWrapper();


  /**
   * Charset to use when calling getResourceAsReader.
   * null means use the system default.
   * 字符集,默认使用系统的,考虑得比较周全,一般我们都没有考虑或直接写死
   */
  private static Charset charset;


 
  public static URL getResourceURL(ClassLoader loader, String resource) throws IOException {
    //把返回的过程委托给了classLoaderWrapper
    URL url = classLoaderWrapper.getResourceAsURL(resource, loader);
    if (url == null) {
      throw new IOException("Could not find resource " + resource);
    }
    return url;
  }


 


 
  public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
    //把返回的过程委托给了classLoaderWrapper
    InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
    if (in == null) {
      throw new IOException("Could not find resource " + resource);
    }
    return in;
  }


  /**
   * Returns a resource on the classpath as a Properties object
   * 得到一个资源的Properties对象,资源是.properties文件
   * @param resource The resource to find
   * @return The resource
   * @throws java.io.IOException If the resource cannot be found or read
   */
  public static Properties getResourceAsProperties(String resource) throws IOException {
    Properties props = new Properties();
    try (InputStream in = getResourceAsStream(resource)) {
      props.load(in);
    }
    return props;
  }


 
  public static Properties getResourceAsProperties(ClassLoader loader, String resource) throws IOException {
    Properties props = new Properties();
    try (InputStream in = getResourceAsStream(loader, resource)) {
      props.load(in);
    }
    return props;
  }



  public static Reader getResourceAsReader(String resource) throws IOException {
    Reader reader;
    if (charset == null) {
      reader = new InputStreamReader(getResourceAsStream(resource));
    } else {
      reader = new InputStreamReader(getResourceAsStream(resource), charset);
    }
    return reader;
  }


 
  public static Reader getResourceAsReader(ClassLoader loader, String resource) throws IOException {
    Reader reader;
    if (charset == null) {
      reader = new InputStreamReader(getResourceAsStream(loader, resource));
    } else {
      reader = new InputStreamReader(getResourceAsStream(loader, resource), charset);
    }
    return reader;
  }


  public static File getResourceAsFile(String resource) throws IOException {
    return new File(getResourceURL(resource).getFile());
  }

  public static File getResourceAsFile(ClassLoader loader, String resource) throws IOException {
    return new File(getResourceURL(loader, resource).getFile());
  }

这个资源类里最重要的只有几个方法,就是实际执行的方法,这里面有涉及另外一个类ClassLoaderWrapper ,看上去所有这些实际加载都是
我们再来看看ClassLoaderWrapper是如何去实际加载资源的

/**
 * A class to wrap access to multiple class loaders making them work as one
 * 一个包装访问多个类加载器使它看起来像在访问一个一样加载资源
 *
 * @author Clinton Begin
 */
public class ClassLoaderWrapper {


  ClassLoader defaultClassLoader;
  ClassLoader systemClassLoader;


  ClassLoaderWrapper() {
    try {
      systemClassLoader = ClassLoader.getSystemClassLoader();
    } catch (SecurityException ignored) {
      // AccessControlException on Google App Engine
    }
  }//核心方法之一,其它一样
   InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
  for (ClassLoader cl : classLoader) {
    if (null != cl) {


      // try to find the resource as passed
      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[] getClassLoaders(ClassLoader classLoader) {
  return new ClassLoader[]{
      classLoader,
      defaultClassLoader,
      Thread.currentThread().getContextClassLoader(),
      getClass().getClassLoader(),
      systemClassLoader};
}

}

这个类做了一件什么事情呢?就是按顺序找到一个合适的类加载器,去加载相应的资源。最核心的方法就是最后一个ClassLoader[] getClassLoaders(ClassLoader classLoader),它返回自己顺序的类加载器列表,一般情况下classLoader和defaultClassLoader都为null,所以使用最多的就是 Thread.currentThread().getContextClassLoader()这个类加载器,这里涉及一个基础知识点JVM类加载过程模模型。

参考文档

MyBatis3源代码阅读(一)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值