jar文件启动加载外部配置文件_你知道mybatis如何加载配置文件

发布时间:2020-12-24 JAR文件启动加载外部配置文件

685b4b158f9b3d38b2b8c4b5d359d815.png

mybatis源码学习

用了这么久mybatis,你知道mybatis是如何加载配置文件的?

经常看到采用如下方式读取配置文件:

InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

好像这成了唯一的加载方式,事实是这样的吗?

话不多说,直接源码

既然是读取文件/资源,那肯定牵涉到io操作。在mybatis源码中我们看到有个io包,路径为:org.apache.ibatis.io,然后我们看下其架构关系:

4a139430e471687b8c09c2943ceafb95.png

由图中可以看出,类Resources聚合并创建`ClassLoaderWrapper对象。

生成stream,getResourceAsStream生成properties,getResourceAsProperties生成Reader,getResourceAsReader生成File,getResourceAsFile生成URL,getResourceURL

上述每种方法都会有对应的重载方法,并调用ClassLoaderWrapper中对应的方法,主要是使用对应的类加载器(没有提供时采用默认)

以Resources#getResourceAsStream方法为例:

public class Resources {     private static ClassLoaderWrapper classLoaderWrapper = new ClassLoaderWrapper();  …      //传入资源文件名称    public static InputStream getResourceAsStream(String resource) throws IOException {        //传入null 类加载,并调用其重载方法        return getResourceAsStream(null, resource);    }    //getResourceAsStream 重载方法实际上调用classLoaderWrapper对象中对应的方法    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;    }  …}  
public class ClassLoaderWrapper {  …  ClassLoader defaultClassLoader;//默认类加载器  ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();//系统类加载器    public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {    return getResourceAsStream(resource, getClassLoaders(classLoader));  }    InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {    //循环遍历各个类加载器,并使用非空的类加载器    for (ClassLoader cl : classLoader) {      if (null != cl) {        // 试着根据资源名称生成输入流        InputStream returnValue = cl.getResourceAsStream(resource);        // 如果returnValue为null,可能是某些类加载器希望已[/]开头,所以会重新尝试加载        if (null == returnValue) {          returnValue = cl.getResourceAsStream("/" + resource);        }        //如果返回值不为null,则返回(否则继续遍历,直至遍历结束)        if (null != returnValue) {          return returnValue;        }      }    }    return null;  }    //创建类加载器组(同时也定义了类加载器的顺序)  ClassLoader[] getClassLoaders(ClassLoader classLoader) {    return new ClassLoader[]{        classLoader,//传入的类加载器        defaultClassLoader,//默认类加载器        Thread.currentThread().getContextClassLoader(),//线程上下文类加载器        getClass().getClassLoader(),//当前类加载器        systemClassLoader//系统类加载器    };  }  …}

以上就是加载资源的过程,其他几种加载方式流程基本相同,不再赘述,有兴趣的朋友可以自行学习。

微观世界,达观人生。

做一名踏实的coder !

更多相关推荐