Mybatis源码阅读,创建Reader对象都干了什么

Reader reader = Resources.getResourceAsReader(“mybatis.xml”);

1.Reader是一个用来读取字符流的抽象类

2.通过Resources.getResourceAsReader()方法将配置文件mybatis.xml加载到一个Reader对象中

3.Resources类中创建了类加载器装载器(ClassLoaderWrapper)的全局静态变量。

ClassLoaderWrapper中封装了五个类加载器,分别有:
一个可定义的ClassLoader;
默认的类加载器ClassLoader;
Thread.currentThread().getContextClassLoader();
getClass().getClassLoader();
ClassLoader.getSystemClassLoader()
源码:

ClassLoader defaultClassLoader;
ClassLoader systemClassLoader;

ClassLoaderWrapper() {
    try {
      systemClassLoader = ClassLoader.getSystemClassLoader();
    } catch (SecurityException ignored) {
      // AccessControlException on Google App Engine
    }
  }
...省略部分代码...
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
    return new ClassLoader[]{
        classLoader,
        defaultClassLoader,
        Thread.currentThread().getContextClassLoader(),
        getClass().getClassLoader(),
        systemClassLoader};
  }

4、getResourcesAsReader()方法:
源码:

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;
  }

代码中的charset是一个静态的全局变量,当它为null时表示使用系统默认的编码;此处使用InputStreamReader来加载资源并用Reader对象接收。
5、getResourceAsStream(resource)方法:
源码:

public static InputStream getResourceAsStream(String resource) throws IOException {
    return getResourceAsStream(null, resource);
  }

继续getResourceAsStream(null,resource)源码

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;
  }

调用此方法时,传入的classLoader为null,也就是说不向类加载器装载器中添加一个自定义的类加载器。方法中,调用classLoaderWrapper的getResourceAsStream来加载资源文件,并用InputStream来接收
6、ClassLoaderWrapper.getResourceAsStream()方法:
源码:

public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
    return getResourceAsStream(resource, getClassLoaders(classLoader));
  }

先看getClassLoaders(classLoader)源码:

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

这就是ClassLoaderWrapper类加载器装载器的庐山真面目了

再继续看getResourceAsStream(resource, getClassLoaders(classLoader))源码

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;
  }

这个方法中,对类加载器装载器进行遍历,如果类加载器不为null就使用类加载器中的getResourceAsStream方法去读取资源并放到InputStream中,又因为有的类加载器需要资源前面带有 “/” 才将其认定为资源进行加载,所以第二个if判断中给resource前加了一个 “/”,最后如果所有类加载器都遍历完成还是没有找到资源的话返回null,否则返回装载了资源的InputStream流。

总结:本质就是使用一个类加载器数组去请求资源,最后以流的方式返回,然后使用Reader接收。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值