21源码剖析——初始化——加载核心配置文件
学习视频资料来源:https://www.bilibili.com/video/BV1R14y1W7yS
文章目录
- 1.测试类
- 2.加载配置文件
- 2.1 Resources
- 2.2 ClassLoaderWrapper
- 2.3. getClassLoaders方法
- 2.4 实际加载资源的方法
- 2.5 异常处理
- 3.总结
1.测试类
public class MybatisTest {@Testpublic void test1() throws IOException {System.setProperty("javax.xml.accessExternalDTD", "all");InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = build.openSession();User user = new User();user.setId(1);user.setUsername("xiaoming");Object o = sqlSession.selectOne("com.mqlyes.dao.UserDao.findByCondition", user);System.out.println(o);}
}
2.加载配置文件
加载配置文件的唯一一行代码:
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
可以看到是通过mybatis.io包下的Resources类进行加载的,点进方法看看。
2.1 Resources
Resources类作用是简化通过类加载器加载资源。InputStream getResourceAsStream(String resource)是它的静态方法,方法里又调用了它的重载方法InputStream getResourceAsStream(ClassLoader loader, String resource),一个参数为类加载器,一个参数为资源路径。这里参数值分别为null和sqlMapConfig.xml。InputStream getResourceAsStream(ClassLoader loader, String resource)方法里又委托给了classLoaderWrapper对象去加载资源。classLoaderWrapper类,看名字就知道是一个类加载包装器,接下来我们点进去这个方法。
2.2 ClassLoaderWrapper
可以看到这个方法又委托给了它的一个重载方法去执行,这个重载方法第1个参数还是资源路径,第2个参数getClassLoaders(classLoader)的返回值。我们再点进:getClassLoaders方法,看看这个方法做了什么。
2.3. getClassLoaders方法
可以看到getClassLoaders返回值是一个 ClassLoader数组,里边有5个元素,下边分别介绍:
[1] classLoader:指定的类加载器。就是这个方法的参数。因为我们传入的是null,所以这里classLoader值为null。
[2] defaultClassLoader:系统默认指定的类加载器。它是classLoaderWrapper对象的成员变量。视频里没有详细解释defaultClassLoader,我看了一下,它可以在外边通过classLoaderWrapper.setDefaultClassLoader设置值,因为我们在外边没有设置,所以这里它也为null。
[3] Thread.currentThread().getContextClassLoader():当前线程绑定的类加载器
[4] getClass().getClassLoader():当前类的类加载器
[5] systemClassLoader:系统类加载器。classLoaderWrapper构造时获取系统类加载器。
后边3个类加载器,在不同的环境中它们不一样的,但是在这个环境中,它们3个是同一个对象,类型是AppClassLoader。注意:是同一个对象,也就是说地址都是一样的。我们可以看一下 getClassLoaders(classLoader)返回结果,前两个都是null所以不显示,后3个都AppClassLoader,且对象地址一样,是同一个对象。
接下来 我们继续向下看委托方法,也是实际加载使用的方法。
2.4 实际加载资源的方法
包了这么多层,终于到了实际执行的方法,hhh 。可以看到这个方法还是比较简单的。方法逻辑:
- 遍历数组中的累加器,如果类加载器不为null,就尝试用这个类加载器加载资源。
- 如果没加载到资源,returnvalue为空,可能是由于资源路径没加"/"导致的,加上后继续重试加载。
- 如果还是加载不到,继续换下一个类加载器,直到能加载到资源。
2.5 异常处理
回到最初的地方,如果获取不到资源输入流,就会抛出异常。
3.总结
- Resources类委托给ClassLoaderWrapper加载核心配置文件,ClassLoaderWrapper是个包装器,里边有多个ClassLoader。在ClassLoaderWrapper中选择正确的ClassLoader加载核心配置文件,并处理一些细节问题,可以使得上层的代码的耦合度,使得代码更加清晰。
- 可以看到Resources.getResourceAsStream,仅仅是将配置文件从磁盘加载到内存,转换成了InputStream 。并没有解析配置文件,具体的解析逻辑下一篇文章介绍。