mybatis学习(3)---加载配置文件
来源:互联网 发布:wps输入数据自动计算 编辑:程序博客网 时间:2024/05/01 02:59
根据上次的小Demo我们来看一下mybatis是如何加载配置文件的。
这是上次的测试成功运行的代码,把其他代码注释,留下创建SqlSessionFactory的代码
package cn.wtzvae.test;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.junit.Test;import cn.wtzvae.dao.PersonDao;import cn.wtzvae.model.Person;import cn.wtzvae.util.SqlSessionFactoryUtil;public class TestFactory { @Test public void test(){ SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtil.getSqlSessionFactory();// SqlSession sqlSession = sqlSessionFactory.openSession();// sqlSession.getConnection();// PersonDao personDao = sqlSession.getMapper(PersonDao.class);// Person p = new Person();// p.setAddress("广东省");// p.setAge(12);// p.setEmail("jinanvae@163.com");// p.setName("啊角");// p.setPhone("110");// personDao.insert(p);// sqlSession.commit();// sqlSession.close(); }}
在看一下SqlSessionFactoryUtil的部分代码。
public static SqlSessionFactory getSqlSessionFactory(){ String path = "mybatis-config.xml"; SqlSessionFactory sqlSessionFactory = null; try { Reader reader = Resources.getResourceAsReader(path);// sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { System.out.println("获取配置文件失败"); e.printStackTrace(); } return sqlSessionFactory; }
其中的Resources类是mybatis自带的类,方法getResourceAsReader(String str);返回Reader。ctrl+左键跟踪一下这个方法,发现如下
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; }
继续跟踪getResourceAsStream(String str); 最终跟踪到ClassLoaderWrapper类(可以用快捷键ctrl+shift+t搜索这个类,eclipse的快捷键)
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) { for (ClassLoader cl : classLoader) { if (null != cl) { System.out.println(cl.getClass().getName()); // 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) { System.out.println("resouce = "+resource); System.out.println(cl.getClass().getName()+" load"); return returnValue; } } } return null; }
上面的方法中三句输出语句是我自己加上的,其中的resource参数是我们自己传进来的,就是”mybatis-config.xml”这个文件名,可以看到上面的语句
InputStream returnValue = cl.getResourceAsStream(resource);
可以获得一个输入流,而这个输入流就是我们的mybatis-config.xml文件的流,得到这个输入流逐步返回给上一层方法,最后SqlSessionFactoryUtil类就能获得mybatis-config.xml文件的流。那现在我们就会好奇,cl.getResourceAsStream(resource); 它又是怎么获取到配置文件的呢。让我们再看这个方法的另外一个参数,ClassLoader[] classLoader。ClassLoader类是类加载器,我们先要了解一下这货是干嘛的。
ClassLoader类:
学java的都知道,java文件编译后会生成class文件。jvm在运行的时候会把class文件加载到jvm的内存方法区中,方法区保存所有class和static变量,为线程共享。而这些要把文件流加载进jvm内存的工作都是类加载器干的活,所以加载mybatis配置文件的工作自然也是ClassLoader的活。
ClassLoader分为三类,分别为Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader。Bootstrap是最顶层的加载器,随jvm启动,负责构造Extension 和App加载器及加载jdk的核心类库,由c++编写。Extension为扩展加载器,加载java_home下的部分类。App系统加载器,加载项目classpath下的资源文件,mybatis的配置文件全由它加载进虚拟机。
回归正题,继续看ClassLoaderWrapper源码。看下面这段源码,ClassLoader[] classLoader参数是getClassLoaders(classLoader)方法返回值传进来的,查看这个方法的源码。
public InputStream getResourceAsStream(String resource, ClassLoader classLoader) { return getResourceAsStream(resource, getClassLoaders(classLoader)); }
下面getClassLoaders(classLoader)方法,其中的systemClassLoader就是我们说的App系统加载类,写了一个输出语句,等会用于验证。
ClassLoader[] getClassLoaders(ClassLoader classLoader) { System.out.println("系统加载类:"+systemClassLoader.getClass().getName()); return new ClassLoader[]{ classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(), systemClassLoader}; }
准备运行测试类,在本次中我们注释了测试类和SqlSessionFactoryUtil中的部分代码,让程序只加载mybatis总配置文件。
运行测试类,输出如下:
系统加载类:sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$AppClassLoader
resouce = mybatis-config.xml
sun.misc.Launcher$AppClassLoader load
输出语句在上面粘的代码里有,可以看出,mybatis配置文件AppClassLoader加载进来的。这里只是加载了配置文件,并没有进行相关验证,在mybatis-config.xml乱输入一些字符也可以运行。
// sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
配置文件的验证是有上面这行代码完成,只不过被我们注释了。现在去掉这行的注释,如果配置文件有错误字符是不能成功运行的。去掉这条注释和sysout(“系统加载类:”…)这条输出,运行输出如下:
sun.misc.Launcher$AppClassLoader
resouce = mybatis-config.xml
sun.misc.Launcher$AppClassLoader load
sun.misc.Launcher$AppClassLoader
resouce = org/apache/ibatis/builder/xml/mybatis-3-config.dtd
sun.misc.Launcher
resouce = cn/wtzvae/mappers/PersonMapper.xml
sun.misc.Launcher
resouce = org/apache/ibatis/builder/xml/mybatis-3-mapper.dtd
sun.misc.Launcher$AppClassLoader load
一共加载了四个配置文件。
//sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
上面语句的执行过程先不深究,继续回到ClassLoaderWapper类的
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader)方法。
方法里面的语句
InputStream returnValue = cl.getResourceAsStream(resource);
我们查看ClassLoad的getResourceAsStream方法,这个已经是jdk自带的类,不属于mybatis。
下面的这个是ClassLoad的getResourceAsStream方法,继续查看getResource方法
public InputStream getResourceAsStream(String name) { URL url = getResource(name); try { return url != null ? url.openStream() : null; } catch (IOException e) { return null; } }
可以看到这个方法存在递归调用,Bootstrap ClassLoader是最顶层的加载器,parent为空,先由它加载资源,没加载成功再由其他ClassLoader加载。
/** * Finds the resource with the given name. A resource is some data * (images, audio, text, etc) that can be accessed by class code in a way * that is independent of the location of the code. * * <p> The name of a resource is a '<tt>/</tt>'-separated path name that * identifies the resource. * * <p> This method will first search the parent class loader for the * resource; if the parent is <tt>null</tt> the path of the class loader * built-in to the virtual machine is searched. That failing, this method * will invoke {@link #findResource(String)} to find the resource. </p> * * @param name * The resource name * * @return A <tt>URL</tt> object for reading the resource, or * <tt>null</tt> if the resource could not be found or the invoker * doesn't have adequate privileges to get the resource. * * @since 1.1 */ public URL getResource(String name) { URL url; if (parent != null) { url = parent.getResource(name); } else { url = getBootstrapResource(name); } if (url == null) { url = findResource(name); } return url; }
再看看jdk文档给getBootstrapResource和findResource方法的定义。
发现这个方法getBootstrapResource是私有的,jdk文档没有说明,这就尴尬了。从源码中有这么一句注释
/**
* Find resources from the VM’s built-in classloader.
*/
看完发觉也没啥卵用
/** * Finds the resource with the given name. Class loader implementations * should override this method to specify where to find resources. </p> * * @param name * The resource name * * @return A <tt>URL</tt> object for reading the resource, or * <tt>null</tt> if the resource could not be found * * @since 1.2 */ protected URL findResource(String name) { return null; }
最后,认真写下来,感觉就对类加载器了解多了一些
- mybatis学习(3)---加载配置文件
- Mybatis 学习 (3) 配置文件
- 【Mybatis】配置文件加载属性
- mybatis加载配置文件测试
- mybatis学习(五)MyBatis主配置文件
- mybatis源码学习之执行过程分析(0)——配置文件加载(io包)
- mybatis 加载配置文件的方法
- Mybatis学习笔记(二)配置文件
- mybatis学习之全局配置文件(五)
- MyBatis配置文件学习
- MyBatis学习总结(3)——优化MyBatis配置文件中的配置
- Mybatis原理学习3:Mybatis的初始化(配置文件的读取和解析)
- mybatis学习总结-核心配置文件mybatis-config.xml(一)
- mybatis学习总结-核心配置文件mybatis-config.xml(一)
- mybatis学习总结-核心配置文件mybatis-config.xml(二)
- mybatis学习总结-核心配置文件mybatis-config.xml(一)
- mybatis学习总结-核心配置文件mybatis-config.xml(二)
- MyBatis学习笔记(四)优化MyBatis配置文件中的配置
- 用git与github建立连接
- 百度地图--路线(步行)
- C语言----链表
- android 控件 recyclerview
- (iOS开发)计算时间差
- mybatis学习(3)---加载配置文件
- Android中解决复写ListView时出现OnScollListener无法监听,这时如果实现标题栏渐变色的话,应该将计算滚动距离的方法,写在不断调用的回调中。
- 洛谷 P1372 又是毕业季I
- android View长按事件简单写法
- 近期开发中用到的一些东西(关于自适应大小,字符串处理,心跳,本地推送,json处理等)
- 代码中特殊的注释技术——TODO、FIXME和XXX的用处
- swiper在IE8下失效
- swift--Swift 3.0实战:和Objective-C的交互需要注意
- 15章上机练习3