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接收。

posted @   有锦  阅读(9)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示