Myabtis源码分析五-Mybatis配置加载完全图解,建造者模式的使用
一起养成写作习惯!这是我参与「日新计划 4 月更文挑战」的第10天,[点击查看活动详情]
一、Mybatis运行流程概述
为了熟悉Mybatis的运行流程,我们先看一段代码
public class MybatisDemo {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
//--------------------第一步:加载配置---------------------------
// 1.读取mybatis配置文件创SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 1.读取mybatis配置文件创SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
inputStream.close();
}
@Test
// 快速入门
public void quickStart() throws IOException {
//--------------------第二部,创建代理对象---------------------------
// 2.获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 3.获取对应mapper
TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
//--------------------第三步:获取数据---------------------------
// 4.执行查询语句并返回单条数据
TUser user = mapper.selectByPrimaryKey(2);
System.out.println(user);
System.out.println("----------------------------------");
// 5.执行查询语句并返回多条数据
// List<TUser> users = mapper.selectAll();
// for (TUser tUser : users) {
// System.out.println(tUser);
// }
}
}
以上是我们一个使用myb设计模式有哪些atis访问数据的demo,通过对快速入门代码的分析,可以把 MyBatis 的运行流程分为三大阶段:
- 初始application化阶段:读取 Xmybatis缓存ML 配置文件和注解中的配置信息appointment源码资本,创建配置对象,并完成各个模块的初始化的工作源码中的图片;
- 代理封装阶段:封装 iBatis 的编程模型,使用 mapper 接源码编辑器口开发的初始化工作;
- 数据访问源码网站阶段:通过 SqlS设计模式的两大主题ession 完成 SQL 的解析,参数的映射、SQLmybatisplus 的执行、结果的解析过程;
今天我们就介绍以appointment下第一个阶段中,Mybatis是approve如何读取配置的
二、配置源码中的图片加载的核心类
2.1 建造器三个appointment核心类
在 MyBatis 中负责加载配置文件的核心类有三个,类图如下:
- BaseBu源码精灵永久兑换码ilder:appstore所有解析器的父类approach,包含配置文件实例,为源码精灵永久兑换码解析文件提供的一些源码通用的方法;
- XMLConfigBuilder: 主要负责解析 mybatmybatis面试题is-config.xml;
- XMLMapperBuilder: 主要负责解析映射配置 Mapper.xm设计模式l 文件;
- XMLStatementBuilder: 主要负责解析映射配置文件中的 SQL 节点;
XMLConfigBuAPPilder、XMLMapper设计模式英文Builder、XMLStatememybatisplusntBuilder 这三个类在配置文件加载过程中非常重要,具体分工如下图所示:
这三个类使用了建造者模式对 configurmybatis工作原理ation 对象进行初始化,但数据库管理系统是没数据库有使用建造者模式
的“肉体”(流式编源码中的图片程风格),只用了灵魂(屏蔽复杂对象源码资本的创建过程),把建造者模式演绎
成了工厂模式;后面还会对这三个mybatis工作原理类源码进行分析;
居然这三个对象使用数据库设计的是建造者模式,那么我们稍后介绍下什么是建造者模式
三、建造者模式
3.1 什么是建造者模式
建造者模式(Buildmybati数据库软件s标签erPattern)使用多个简单源码交易平台的对象一步一步构建成一个复杂的对象。这种类型的设计模式属mybatis动态sql于创建型模式,它提供了一种创建对象的最佳方式。
建造者模式类图如下:
各要素如下:
- Product:要创建的复杂对象
- Builder数据库设计:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象apprecia数据库te的哪些部分的创建,并不涉设计模式一般用来解决什么问题及具体的对象部件的创建;
- Conapplicationcret数据库系统概论eBuiappearlder:实现 Builder 接口,针对不同的商业逻辑,具数据库管理系统体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例;
- Dmybatis缓存irector:调用具体建造者来创application建复杂对象数据库源码系统概论的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种源码交易平台顺序创建源码网站;
应用举例:红包的创建是个复杂的过程,可以使用构建者模式进行创建
代MyBatis码示例:
1、红包数据库数据库系统概论系统概论第五版课后答案对象RedPacket
public class RedPacket {
private String publisherName; //发包人
private String acceptName; //收包人
private BigDecimal packetAmount; //红包金额
private int packetType; //红包类型
private Date pulishPacketTime; //发包时间
private Date openPacketTime; //抢包时间
public RedPacket(String publisherName, String acceptName, BigDecimal packetAmount, int packetType, Date pulishPacketTime, Date openPacketTime) {
this.publisherName = publisherName;
this.acceptName = acceptName;
this.packetAmount = packetAmount;
this.packetType = packetType;
this.pulishPacketTime = pulishPacketTime;
this.openPacketTime = openPacketTime;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getAcceptName() {
return acceptName;
}
public void setAcceptName(String acceptName) {
this.acceptName = acceptName;
}
public BigDecimal getPacketAmount() {
return packetAmount;
}
public void setPacketAmount(BigDecimal packetAmount) {
this.packetAmount = packetAmount;
}
public int getPacketType() {
return packetType;
}
public void setPacketType(int packetType) {
this.packetType = packetType;
}
public Date getPulishPacketTime() {
return pulishPacketTime;
}
public void setPulishPacketTime(Date pulishPacketTime) {
this.pulishPacketTime = pulishPacketTime;
}
public Date getOpenPacketTime() {
return openPacketTime;
}
public void setOpenPacketTime(Date openPacketTime) {
this.openPacketTime = openPacketTime;
}
@Override
public String toString() {
return "RedPacket [publisherName=" + publisherName + ", acceptName="
+ acceptName + ", packetAmount=" + packetAmount
+ ", packetType=" + packetType + ", pulishPacketTime="
+ pulishPacketTime + ", openPacketTime=" + openPacketTime + "]";
}
}
2、构建对象
public class Director {
public static void main(String[] args) {
RedPacket redPacket = RedPacketBuilderImpl.getBulider().setPublisherName("DK")
.setAcceptName("粉丝")
.setPacketAmount(new BigDecimal("888"))
.setPacketType(1)
.setOpenPacketTime(new Date())
.setPulishPacketTime(new Date()).build();
System.out.println(redPacket);
}
}
Pmybatis一级缓存和二级缓存S:流mybatis标签式编程风格越来越流行,如 zookeeper 的 Curator、JDK8 的流式编程等等都是例子。流式编程的优点在于代码编程性更高、可读性appstore更好,缺点在于源码编辑器下载对程序员编码要求更高、不太利于调试。建造者模式是实现流式编程风格的一种方式apple;
3.2 与工厂模式区别
建造者模式应用场景如数据库下:
- 需要生成的对象具有复杂的内部结构appear,实例化对象时要屏蔽掉对象代码mybatis面试题与复杂对象的实例化过程解耦,可以使用建造者模式;简而言appstore之,如果“遇到多个构源码交易平台造器参数时要考虑用构建器”;MyBatis
- 对象源数据库系统工程师码网站的实例化是依赖各个组件的产生以及装配顺序设计模式一般用来解决什么问mybatis动态sql题,关注的是一approve步一步地设计模式有哪些MyBatis组装出目标对
- 象,可以使用建造器源码编程器模式;
建造者模式与工程模式的区别在于:
设计模式 | 形approve象比喻 | 对象复杂度 | 客户端参与程度 |
工厂模式 | 生产MyBatis大众版 | 关注的是一个产品整体,无须关心产品的各部分是如何创建出mybatis一级缓存和二级缓存来apple的; | 客户端对产品的创application建过程参与度低,对象实例化时属性值相对比较固定; |
建造者模式 | 生产定制版 | 建源码之家造的对象更加复杂,是一个复合产品,它由各个部件复合而成,部件不同产品对象不同,生成的产品粒度细; | 客户端参与了产品的创建,决定设计模式面试题数据库了产品的类型和内容,参与度高;适合实例化对象时属性变化频繁的场景;mybatis注解 |
四、Configuration 对象介绍源码
实例化并初始化 Configurappr数据库设计oachation 对象是第一个阶段的最终目的,所以熟悉 configurat设计模式23模式介绍ion 对
象是理解第一个阶段代码的核心;conf源码编辑器igurat源码编辑器ion 对象的关键属性解析如下:mybatis注解
- MapperRegistry设计模式及其应用场景:mapper 接口动源码中的图片态代理数据库查询语句工厂类的注册中心。在 MyBatis 中,通过mapperProxy 实现 In数据库vocationHandler 接口,MapperProxyFactory 用于生成动mybatis注解态代理的实例对象;
- ResultMap:用于解析 mapper.xml 文件中的 resultappstoreMap 节点,使用 ResultMapping 来封装id,reMyBatissult 等子元素;
- MappedStatement:用于存储 mapper.xml 文件中的 sele源码1688ct、insert、update 和 delete 节数据库原理点,同时还包含了这些节点的很多重要属性;
- SqlSource:用于创建 BoundSql,mapper.xml 文件源码中的 sql 语句会被解析成 BoundSql 对象,经过解析 BoundSql 包含的语句最终仅仅包含?占位符,可以直接提交给数据库执行;
Con源码1688figura设计模式23模式介绍tion对象图解:
需要特别注意的是 Conappstorefiguration 对象在 MyBatis 中是单例的,生命周期是应用级的,换句话说只要 MyBatis 运行 Confmybatis缓存iguration 对象就会独一无二的存在;在 M源码1688yB数据库系统的核心是atis 中仅在
org.ap设计模式有哪些acmy设计模式及其应用场景batis缓存he.ibatis.builder.xml.XMLConfigBuilder.XMLConfigBuilder(XPathParser, String, Properties)中有实例化 configuration 对源码编程器象的代数据库系统的核心是码,如下图:
Coappetitenfiguration 对象的初始化(属性复制),是在建造 SqlSessionfactory 的过程中进行的,接下
来分析第一个阶段的内部流程;
五、配置加载流程解析
5.1 配置加载过程
可以把第一个阶段配置appreciate加载过程分解为四个步骤,四个步骤如下图:
第一步:通过 SqlSessionFactoryBuil数据库设计der 建造 SqlSessionFactory,并创建 XMLConfigBuilder 对
象 读 取 MyBatis 核 心 配 置 文 件 , 见源码方 法 :
o数据库系统的核心是rg.apache.ibat设计模式一般用来解决什么问题is.sess数据库系统概论第五版课后答案ion.SqlSessionFact数据库管理系统oryBuilder.build(Reader, Stringapproach, Properties):
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
//读取配置文件
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());//解析配置文件得到configuration对象,并返回SqlSessionFactory
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
第源码中的图片二步:进入 XMLConfigBuilder 的 parseConfiguratappearanceion 方法,对 MyBati设计模式的两大主题s 核心配置文件的各个
元素进行解析,读取元素信息后填充数据库原理到 configuration 对象。在 XMLConfigBuilder 的
mapperElement()数据库软件方法中通过 XMLMapperBuilder 读取所有 mapper.xml 文件;见方法:
org.apache.ibatis.builder.x源码之家ml.XMLConfigBuilder.parseConfigurapplicationation(XNode);
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
//解析<properties>节点
propertiesElement(root.evalNode("properties"));
//解析<settings>节点
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
//解析<typeAliases>节点
typeAliasesElement(root.evalNode("typeAliases"));
//解析<plugins>节点
pluginElement(root.evalNode("plugins"));
//解析<objectFactory>节点
objectFactoryElement(root.evalNode("objectFactory"));
//解析<objectWrapperFactory>节点
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
//解析<reflectorFactory>节点
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);//将settings填充到configuration
// read it after objectFactory and objectWrapperFactory issue #631
//解析<environments>节点
environmentsElement(root.evalNode("environments"));
//解析<databaseIdProvider>节点
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
//解析<typeHandlers>节点
typeHandlerElement(root.evalNode("typeHandlers"));
//解析<mappers>节点
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
第数据库软件三步:XMLMapperBuilderappetite 的核心方法为 conf设计模式23模式介绍igurationEappointmentlmybatis中$和井号区别ement(XNode),该方法对源码编程器 map数据库设计per.xml 配置文件的各个元素进行解析,读取元素信息后填充到 configura数据库有哪几种tion 对象。
private void configurationElement(XNode context) {
try {
//获取mapper节点的namespace属性
String namespace = context.getStringAttribute("namespace");
if (namespace == null || namespace.equals("")) {
throw new BuilderException("Mapper's namespace cannot be empty");
}
//设置builderAssistant的namespace属性
builderAssistant.setCurrentNamespace(namespace);
//解析cache-ref节点
cacheRefElement(context.evalNode("cache-ref"));
//重点分析 :解析cache节点----------------1-------------------
cacheElement(context.evalNode("cache"));
//解析parameterMap节点(已废弃)
parameterMapElement(context.evalNodes("/mapper/parameterMap"));
//重点分析 :解析resultMap节点----------------2-------------------
resultMapElements(context.evalNodes("/mapper/resultMap"));
//解析sql节点
sqlElement(context.evalNodes("/mapper/sql"));
//重点分析 :解析select、insert、update、delete节点 ----------------3-------------------
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
} catch (Exception e) {
throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
}
}
在 XMLMaappstorepperBuilder 解析过程中mybatis注解,有四个点需要注意:
- resultMapElements(List)方法用源码交易平台于解析 resultMap 节点,这个方法非常重要, 一定要跟源ap源码编程器ple码理解;解析完之后数据保存在 configuration 对象的 resultMappearanceaps 属性中;如下图
- 2XMLMa源码编辑器下载pperBuilder 中在实例化二级缓存(见 cac源码编辑器下载heElement(XNode))、实例化 resultMap (见 re设计模式英文sultMapElement数据库设计s(List))过程中都使用了approach建造者设计模式一般用来解决什么问题模式,而且是建造者模 式的典型应用;
- XMLMapperBuilder 和 XMLMappmybatispluserStatmentBuilder 有 自 己 的 “ 秘 书 ” MapperBuilderAssistant。XMLMa设计模式的集体教学活动方案pperBuil源码编程器der 和 X设计模式面试题MLMapperStatmappearentBuilder 负责解析 读取配置文件里面的信设计模式一般用来解决什么问题息,MapperBu设计模式及其应用场景ilderA源码精灵永久兑换码ssistant 负责将信息填充到 configuration。 将文件appetite解析和数据的填充的工作分离在数据库系统的核心是不同的类中,符合单一职责原则;
- 在数据库 buildStatementFro设计模式面试题mContextappreciate(List)方法中,创建 XMLStatmentBuilde源码编辑器r 解析 Mapper.xml 中 select、inserapproacht、update、delete 节点
第四步源码精灵永久兑换码数据库软件:在 XMLStatmentBuilderapple 的 parseStatementNode()方法中,对 Mapper.xml 中 select、 insert、upda数据库系统工程师te、delete 节点进行解析,源码精灵永久兑换码并调用 MapperBuilderA数据库软件ssistant 负责将mybatis中$和井号区别信息填充到 configuration。在理解 par设计模式有哪些seStatementNod()方法之前mybatis怎么读,有必要了appreciate解 MappedStatement源码编辑器approve,这个 类 用 于 封 装 select 、 insert 、 update 、 delete 节 点 的 信 息 ;源码资本 如 下 图 所 示 :
至此,整个Mymyb数据库查询语句atis中$和井号源码编程器区别batis的配置即加载完APP毕,整个加载流程图如下: