今天我们主要分析一下mybatis从SqlSessionFactoryBuilder构建SqlSessionFactory,再通过SqlSessionFactory获取SqlSession,进而获取Mapper对象的过程。即下面四行代码
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
一、获取XML配置文件的输入流
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
首先我们调用的是Resources中的单个String参数的getResuorceAsStream方法,这个方法内部调用的是另一个带有类加载器参数的方法。
带有类加载器的方法中调用了ClassLoaderWrapper包装类进行获取输入流
我们再进入ClassLoaderWrapper的getResouceAsStream的方法中,我们可以看到该方法调用了另一个需要数据源和类加载器数组的方法
我们看一下这个类加载器数组是如何得来的,可以看到除了传入的类加载器,数组中还有ClassLoaderWrapper中成员变量默认的类加载器、当前线程的类加载器、当前对象的类加载器以及系统类加载器总共五个。
而getResourceAsStream方法中则是遍历类加载器数组,逐个尝试使用类加载器进行获取输入流,并且有些类加载器在加载类时需要前缀 " / " 所以源码中也将这种情况包括在内。最终返回输入流对象。
该部分流程图如下
二、获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
因为SqlSessionFactoryBuilder我们最好用完即丢,所以这里使用匿名对象直接调用build方法,我们进入build方法中,发现调用的是另一个包含InputStream、environment、Properties的方法
该方法中创建了XMLConfigBuilder对象,使用XPath解析获取对应于我们的mybatis’核心配置文件的Configuration类对象,然后创建DefaultSqlSessionFactory(SqlSessionFactory的实现子类)并作为构造器的参数传递进去。最终返回子类对象。
该部分流程图:
三、获取SqlSession对象
调用的实际上是DefaultSqlSession中的openSessionFromDataSource方法
首先读取出运行环境,然后通过环境构建出TransactionFactory,再通过工厂创建事务对象,创建Excutor对象,默认是创建SimpleExcutor,如果开启缓存,会将SimpleExcutor封装进入CachingExcutor中
最后创建DefaultSqlSession返回对象
四、获取mapper
调用的是Configuration中的getMapper,方法中调用的又是MapperRegistry的getMapper方法,最终通过代理模式和工厂设计模式创建Mapper对象
五、总体流程
叙述总结:
1.读取配置文件到流中
InputStream is = Resources.getResourceAsStream(resource);
该方法核心是通过ClassLoaderWrapper的getResouceAsStream方法
该方法的核心是通过类加载器的数组进行加载配置文件
并且该方法直接利用传入的配置文件名进行加载不能正确加载
对加'/'的情况也会进行判断能否正确加载,最终返回一个输入流。
2.构建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
通过SqlSessionFactoryBuilder来创建SqlSessionFactory
首先必须我们需要一个对象来表示我们的config配置文件
在build方法中,我们创建了XMLConfigBuilder,解析我们的XML配置文件为
Configuration对象,然后创建DefaultSqlSessionFactory对象(SqlSessionFactory的子类)
在构造方法中传入Configuration对象完成对SqlSessionFactory的实例化
3.获取SqlSession
SqlSession sqlSession = SqlSessionFactory.openSession();
DefaultSqlSessionFactory调用openSession来进行来进行获取DefaultSqlSession
然后调用的是openSessionFromDataSource,先通过SqlSessionFactory读取的配置文件
获取运行环境Environment,然后通过事物工厂获取事物对象,最后通过configuration
对象获取excutor执行器对象,默认创建的是simpleeccutor,并且封装在cachingExcutor中
最后传入configuration、autocommit(是否开启事务)、excutor(内部其实封装了事务对象,
在获取的时候进行的封装)调用new defaultSqlSession获得对象
4.获取mapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
首先调用的是DefaultSqlSession中的getMapper方法,方法中调用的是配置文件对象的getMapper(
因为我们映射文件的位置本身就写在配置文件中,所以并不难理解configuration.<T>getMapper(type, this)
然后Configuration中又一个mapperRegistry对象,代表着我们配置文件中的mappers,通过它我们来调用
getMapper方法进行获取对象。然后我们获取我们需要的Mapper对应的mapperProxyFactory映射器代理工厂
首先通过工厂获取映射器代理,然后通过代理类帮我们完成功能
来源:oschina
链接:https://my.oschina.net/u/4330568/blog/4463365