一 简介:
1.对于MyBatis的源码分析从SqlSessionFactory开始
2.对于源码分析,有些地方的确无法明白,所以只能将结论抛出。
二 配置流的读取
1.我们使用iBatis包中的Resources工具类的getResourceAsStream方法将配置文件转化为流。
2.这里我们传递的ClassLoder(类加载器)为null值,resouce为配置文件的地址,并调用同样位于ibatis的io包中的ClassLoaderWrapper的getResourceAsStream方法创建流
3.在方法getResourceAsStream中,我们将resoure地址转交给下一个方法,并将null(classLoader)移交给getClassLoader()
我们得到一个ClassLoader数组,第一个值为null,第二个值为默认类加载器,第三个值为当前线程的上下文类加载器,第四个值为当前类(ClassLoaderWrapper)的类加载器,第五个为系统类加载器,的确不懂这五个类加载器是干嘛的
4.循环遍历这几个类加载器并且通过类加载器获得流,如果获得失败则加上"/"再次尝试,失败后继续下一个,当类加载器成功获得输入流后,则返回输入流,退出该方法,若这几个类加载器都失败后则返回null,报异常处理。
5.类加载器获得输入流,通过ClassLoader类的getResource方法讲文件转化为URL,并通过得到的URL使用openStream方法获得流,否则返回null值
6.这里是三种获得URL对象的方法,基于一些原因(实体类太多,是在找不到是哪个类),不继续往下看了。
7.不过我们可以通过错误的配置发现,流的创建并不会有报错,只会找不到当前文件返回空值错误,而报错全部在builder方法中,也就是SqlSessionFactory的创建时,就试试验证配置信息在工厂创建时。而流处理并不会验证。
三 输入流文件解析成为Configuration对象
1.SqlSessionFactoryBuilder的Builder方法
2.我们将InputStream传递进入,第二个参数(environment)设置为null,Properties( 配置文件地址)设置为null,进入build方法;
3.使用XMLConfigBuilder将三个参数传入并完成并生成XMLConfigBuilder对象(看下面),并调用这个parser(解析者)的方法parse(解析)得到SqlSessionFactory对象并返回,如果出现异常就进入异常处理,并在结束重置掉ErrorContext这个错误上下文,管理InputStream流文件。
4.传递进来后会生成一个XPathParser(XML环境解析器)内部参数除了两个null一个reader外多了一个true(确认)和一个XMLMapperEntityResolver(XML映射文件实体解析器)
5.这个实体解析器内部定义了 MyBatis中的各种DTD(语法类型定义器),用于判断MyBatis和ibatis的Config(总配置文件)和Mapper(映射文件)的语法规则,而XPathParser就是通过这些DTD文件来解析Config文件以及Mapper映射文件的,至于如何解析,也就是你平时中配置的目的。
6.我们知道parser是XPathParser的实例对象,并且内部有DTD的解析规则,而environment为null,props同样为null,可以知道目前为止,我们只通过输入流文件获得了一个内部具有DTD规则和配置输入流文件的XPathParser的实例对象,且这个对象将调用调用parse方法(图3)解析出Configuration的实例对象并将对象传入到build方法中获得一个DefaultSqlSessionFactory对象。
注:目前来说已经不用看下去了(闲的蛋疼可以继续看):我们知道最终在XMLConfigBuilder对象中创建一个XPathPaser(解析器对象)且该对象内部拥有DTD(语法规则)和输入流文件(配置信息),且通过该对象的parse(解析)将流转化为Configuration对象,并将Configuration对象传入Build方法,生成一个DefaultSqlSessionFactory对象。
7.解析方法一样是判断parsed(是否被解析?默认为false),如果解析了该对象失效,如果没有被解析,采用ParseConfiguration方法来将获得配置信息,而XPathParser对象则调用evalNode(解析节点)方法解析,并且获得XNode(Xml节点)
8.显然节点中是以树型结构来传出的,我们将所有配置文件根据这些节点的递归函数(evalNode)来解析这个XML树形结构,获得每个节点的真实值,无论是environment还是mapper还是properties都是层层解析下来的,显然所有的XML文件都是以这样的方式来存储配置的,无论是哪个节点的报错最终都会上传到BuilderException中并上传到控制台。关于XMLConfigurBuilder的分析到此为止,往后都是节点的解析了。
9.算了手贱,节点解析则是通过传入一个Object(实际上是this.node当前节点)和String类型的expression(指节点的名称吧大概),调用evaluate方法最终获得一个Node对象,并通过三目运算法来获得一个新的XNode(包含有this(指输入流以及DTD),node(此次生成的节点),variables(计数器,不太明白)),根据树形结构解析时,不仅仅需要解析当前节点,还需要把子节点加上计数器和解析规则来创建新的节点,递归解析。
四 DefaultSqlSessionFactory对象的创建
这就没什么好说的了,DefaultSqlSessionFactory内部有一个Configuration对象,并将传入的Configuration值传递给当前对象,Factory并不会在实例化的时候做什么。只会在openSession的时候通过Configuration来创建SqlSession,这留到下一节说。