读取资源文件
MyBatis中读取资源文件示例代码:
// 资源文件路径,MyBatis配置文件
String resource = "mybatis-config.xml";
// 读取资源文件,获取一个输入流对象
InputStream inputStream = Resources.getResourceAsStream(resource);
在 MyBatis 中使用Resource
的getResourceAsStream()
方法读取资源文件,在getResourceAsStream()
方法内部,又去调用了ClassLoaderWrapper
的getResourceAsStream
方法。ClassLoaderWrapper
类中getResourceAsStream
方法的源码如下:
/**
* 依次使用5种类加载器读取资源文件
* @param resource 资源文件路径
* @param classLoader 类加载器
* @return 资源文件流,可能为null
*/
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
// 依次使用5种类加载器
for (ClassLoader cl : classLoader) {
// 如果类加载器不为空
if (null != cl) {
// 读取资源文件
InputStream returnValue = cl.getResourceAsStream(resource);
// 如果上步读取到的内容为空,会在资源文件路径前添加斜杠,然后再次读取资源文件
if (null == returnValue) {
returnValue = cl.getResourceAsStream("/" + resource);
}
// 如果成功读取到资源文件内容,返回资源文件流
if (null != returnValue) {
return returnValue;
}
}
}
// 如果使用所有的类加载器后仍然没有成功读取资源文件,则返回null
return null;
}
其中参数resource
为资源文件路径,classLoader
为ClassLoaderWrapper
中内置的类加载器数组。
使用ClassLoaderWrapper
读取资源文件或者加载类时,依次使用自定义类加载器、默认类加载器、线程上下文类加载器、MyBatis类加载器、系统类加载器。如果类加载器为空或者读取到的内容为空,会继续尝试使用下一个类加载器。
读取资源文件时,单个类加载器执行流程如下图:
类加载器
ClassLoaderWrapper
中封装了5种类加载器,这5种类加载器可以通过getClassLoaders
方法获取。getClassLoaders
方法代码如下所示:
/**
* 获取所有类加载器
* @param classLoader 自定义类加载器
* @return 所有类加载器
*/
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
return new ClassLoader[] {
classLoader,
defaultClassLoader,
// 当前线程的上下文类加载器
Thread.currentThread().getContextClassLoader(),
// MyBatis类的类加载器
getClass().getClassLoader(),
// 系统类加载器
systemClassLoader
};
}
由上面的代码可以看出,5种类加载器分别为:
- 自定义类加载器,可能为 null;
- 默认类加载器,可能为 null;
- 线程上下文类加载器;
- MyBatis类加载器;
- 系统类加载器,在
ClassLoaderWrapper
;