Mybatis的初始化 建造者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式,属于创建型模式,它提供了一种创建对象的最佳方式。
Builder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建;
ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例;
Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息, 只负责保证对象各部分完整创建或按某种顺序创建;
Product:要创建的复杂对象
与工厂模式区别
对象复杂度
建造者建造的对象更加复杂,是一个复合产品,它由各个部件复合而成,部件不同产品对象不同,生成的产品粒度细;
在工厂方法模式里,我们关注的是一个产品整体,无须关心产品的各部分是如何创建出来的;
客户端参与程度
建造者模式,导演对象参与了产品的创建,决定了产品的类型和内容,参与度高;适合实例化对象时属性变化频繁的场景;
工厂模式,客户端对产品的创建过程参与度低,对象实例化时属性值相对比较固定;
建造者模式的使用场景
1、需要生成的对象具有复杂的内部结构,实例化对象时要屏蔽掉对象内部的细节,让上层代码与复杂对象的实例化过程解耦,可以使用建造者模式;简而言之,如果“遇到多个构造器参数时要考虑用构建器”;
2、一个对象的实例化是依赖各个组件的产生以及装配顺序,关注的是一步一步地组装出目标象,可以使用建造器模式;
XMLConfigBuilder: 主要负责解析mybatis-config.xml;
XMLMapperBuilder: 主要负责解析映射配置文件;
XMLStatementBuilder: 主要负责解析映射配置文件中的SQL节点;
mybatis-config.xml是如何加载到Configuration对象中的。
Configuration : Mybatis启动初始化的核心就是将所有xml配置文件信息加载到Configuration对象中, Configuration是单例的,生命周期是应用级的,看类的属性熟悉吗?就是配置文件mybatis-config.xml里可以配置的那些信息
话说回来,看是如何加载mybatis-config.xml的
那么跟一下SqlSessionFactoryBuilder对象的build方法,参数只有一个inputstream。
看这个是new XmlConfigBuilder 对象,说明利用这个对象的parse()方法先解析
然后看是如何解析的,跟进parse()方法:
这个“/configuration”字符串是什么意思?就是mybatis-config.xml的根目录
<configuration>
</configuration>
解析这个中间的标签,就是下图这种
那么再看:
说白了就是由不同的函数去解析不同的标签。
随便挑几个看一下 properties,里面可以配置很多吧 可以配resource,url等
mappers里面也可以配很多吧 package class resource name 等
看上图的这段代码:
如果mappers里的mapper的resource不为空,那么就去解析,使用 XMLMapperBuilder。XMLMapperBuilder: 主要负责解析映射配置文件;看下怎么解析的,跟进去parse(),注意这里是解析实体类对应的xml文件,下图字符串“/mapper”是xml的根节点,在这个根节点下是写sql标签的,还写resultMap的。
那就继续跟if下面这句代码咯,configurationElement()
但是并没有看到建造者模式有什么应用呢?别急,继续看上图cacheElement(context.evalNode("cache"))这段代码:
继续跟红框的方法:(builderAssistant是下图这个类的对象)
上图build出来之后是要放到configuration里去的。
下图是CacheBuilder的字段
build()方法
分析这个方法之前,看一下一个图:
是怎么加载到configuration对象里的呢?
首先在configuration对象里看一下:
那就看value = resultMap这个类:
xml中的每一个resultMap都对应一个resultMap类
看上图中 List<ResultMapping> 泛型这个类。
然后具体看代码
上图的resultMapElements()
看上图的296行代码add()里面的new对象
继续跟上图的红框
add()之后完毕
剩下的其实也没啥就是读取.xml所有的的resultmap,然后塞到configuration对象里去。
下来就是解析sql语句了:
那么sql语句解析是:XMLStatementBuilder
sql语句解析的时候中级目标是mappedStatment
MappedStatement:用于存储mapper.xml文件中的select、insert、update和delete节点,同时还包含了这些节点的很多重要属性;
具体看红框
那么初始化
再看一下下图红框
SqlSource:mapper.xml文件中的sql语句会被解析成SqlSource对象,经过解析SqlSource包含的语句最终仅仅包含?占位符,可以直接提交给数据库执行
跟进去:
那具体来看一下是怎么解析sql语句的:
首先还是回到
直接看这个parseStatementNode()
这个调用的意思就是 把xml中的sql语句封装成SqlSource
再跟实现类:建造者模式:
将SqlSource创建交给了XMLScrpitBuilder。根据是否是动态的语句,创建DynamicSqlSource或是RawSqlSource对象,并返回
上图方法第一句代码
MixedSqlNode是SqlNode的一个实现,包含了各个子节点,用来遍历输出子节点。SqlNode还有很多不同的实现,分别对应不同的节点类型。对应关系如下:
跟进去这个方法
就跟到这个,往下不跟了,很麻烦
总之红框很重要
那么到现在就是已经解析了cache、resultMap、curd。
映射器的关键类
Configuration : Mybatis启动初始化的核心就是将所有xml配置文件信息加载到Configuration对象中, Configuration是单例的,生命周期是应用级的;
MapperRegistry:mapper接口动态代理工厂类的注册中心。在MyBatis中,通过mapperProxy实现 InvocationHandler接口,MapperProxyFactory用于生成动态代理的实例对象;
ResultMap:用于解析mapper.xml文件中的resultMap节点,使用ResultMapping来封装id,result等子元素;
MappedStatement:用于存储mapper.xml文件中的select、insert、update和delete节点,同时还包含了这些节点的很多重要属性;
SqlSource:mapper.xml文件中的sql语句会被解析成SqlSource对象,经过解析SqlSource包含的语句最终仅仅包含?占位符,可以直接提交给数据库执行;