MyBatis源码第一天

手机游戏开发者 2024-10-7 00:05:20 116 0 来自 中国
一、MyBatis分析全局设置文件

1.MyBatis先容

MyBatis是一个恒久层的ORM框架,利用简朴,学习成本较低。可以实行本技艺写的SQL语句,比力机动。但是MyBatis的主动化程度不高,移植性也不高,偶然从一个数据库迁徙到别的一个数据库的时间须要本身修改设置,以是称只为半主动ORM框架。
2.传统JDBC和Mybatis相比的弊病

2.1传统JDC
1.png 传统JDBC的题目如下:
1.数据库连接创建,开释频仍造成资源的浪费,从而影响体系性能,利用数据库连接池可以办理题目。
2.sql语句在代码中硬编码,造成代码的不易维护,现实应用中sql的变革大概较大,sql代码和java代码没有分离开来维护不方便。
3.利用preparedStatement向有占位符转达参数存在硬编码题目,由于sql中的where子句的条件不确定,同样是修改不方便。
4.对结果集中分析存在硬编码题目,sql的变革导致分析代码的变革,体系维护不方便。
2.2mybatis对传统的JDBC的办理方案
1、数据库连接创建、开释频仍造成体系资源浪费从而影响体系性能,如果利用数据库连接池可办理此题目。
办理:在SqlMapConfig.xml中设置数据连接池,利用连接池管理数据库链接。
2、sql语句写在代码中造成代码不易维护,现实应用sql变革的大概较大,sql变更须要改变java代码。
办理:将sql语句设置在XXXXmapper.xml文件中与java代码分离。
3、向sql语句传参数麻烦,由于sql语句的where条件不肯定,大概多也大概少,占位符须要和参数逐一对应。
办理:Mybatis主动将java对象映射至sql语句,通过statement中的parameterType界说输入参数的范例。
4、对结果集分析麻烦,sql变革导致分析代码变革,且分析前须要遍历,如果能将数据库记录封装成pojo对象分析比力方便。
办理:Mybatis主动将sql实行结果映射至java对象,通过statement中的resultType界说输出结果的范例。
2.3Mybatis的功能架构分为三层
a.API接口层:提供给外部利用的接口API,开发职员通过这些当地API来利用数据库。接口层一吸收到调用请求就会调用数据处理惩罚层来完成具体的数据处理惩罚。
b.数据处理惩罚层:负责具体的SQL查找、SQL分析、SQL实行和实行结果映射处理惩罚等。它告急的目标是根据调用的请求完成一次数据库利用。
c.根本支持层:负责最根本的功能支持,包罗连接受理、事件管理、设置加载和缓存处理惩罚,这些都是共用的东西,将他们抽取出来作为最根本的组件,为上层的数据处理惩罚层提供最根本的支持。
一个Mybatis最简朴的利用列子如下:
3.png 总结下就是分为下面四个步调:
1.从设置文件(通常是XML文件)得到SessionFactory;
2.从SessionFactory得到SqlSession;
3.通过SqlSession举行CRUD和事件的利用;
4.实行完相干利用之后关闭Session。
3.启动流程分析

通过上面代码发现,创建SqlSessionFactory的代码在SqlSessionFactoryBuilder中,进去一探毕竟:
5.png 下面我们看下分析设置文件过程中的一些细节。
先给出一个设置文件的列子:
6.png 下面是分析设置文件的焦点方法:
7.png 上面分析流程竣事后会天生一个Configration对象,包罗全部设置信息,然后会创建一个SqlSessionFactory对象,这个对象包罗了Configration对象。
4.对于MyBatis启动的流程(获取SqlSession的过程)这边简朴总结

SqlSessionFactoryBuilder分析设置文件,包罗属性设置、别名设置、拦截器设置、情况(数据源和事件管理器)、Mapper设置等;分析完这些设置后会天生一个Configration对象,这个对象中包罗了MyBatis须要的全部设置,然后会用这个Configration对象创建一个SqlSessionFactory对象,这个对象中包罗了Configration对象。
二、Mybatis-计划模式总结

固然我们都知道有26个计划模式,但是大多停顿在概念层面,真实开发中很少碰到,Mybatis源码中利用了大量的计划模式,阅读源码并观察计划模式在此中的应用,可以大概更深入的明确计划模式。
Mybatis至少碰到了以下的计划模式的利用:
                Builder模式,比方SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;
工厂模式,比方SqlSessionFactory、ObjectFactory、MapperProxyFactory;
单例模式,比方ErrorContext和LogFactory;
署理模式,Mybatis实现的焦点,好比MapperProxy、ConnectionLogger,用的jdk的动态署理;尚有executor.loader包利用了cglib大概javassist到达延长加载的结果;
组合模式,比方SqlNode和各个子类ChooseSqlNode等;
模板方法模式,比方BaseExecutor和SimpleExecutor,尚有BaseTypeHandler和全部的子类比方IntegerTypeHandler;
适配器模式,比方Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现;
装饰者模式,比方Cache包中的cache.decorators子包中等各个装饰者的实现;
迭代器模式,比方迭代器模式PropertyTokenizer;
接下来挨个模式举行解读,先先容模式自身的知识,然后解读在Mybatis中怎样应用了该模式。
1.Builder模式
Builder模式的界说是“将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建差异的表现”,它属于创建类模式,一样平常来说,如果一个对象的构建比力复杂,超出了构造函数所能包罗的范围,就可以利用工厂模式和Builder模式,相对于工厂模式会产出一个完备的产物,Builder应用于更加复杂的对象的构建,以致只会构建产物的一个部分。
在Mybatis情况的初始化过程中,SqlSessionFactoryBuilder会调用XMLConfigBuilder读取全部的MybatisMapConfig.xml和全部的*Mapper.xml文件,构建Mybatis运行的焦点对象Configuration对象,然后将该Configuration对象作为参数构建一个SqlSessionFactory对象。
此中XMLConfigBuilder在构建Configuration对象时,也会调用XMLMapperBuilder用于读取*Mapper文件,而XMLMapperBuilder会利用XMLStatementBuilder来读取和build全部的SQL语句。
在这个过程中,有一个相似的特点,就是这些Builder会读取文件大概设置,然后做大量的XpathParser分析、设置或语法的分析、反射天生对象、存入结果缓存等步调,这么多的工作都不是一个构造函数所能包罗的,因此大量采取了Builder模式来办理。
对于builder的具体类,方法都多数用build*开头,好比SqlSessionFactoryBuilder为例,它包罗以下方法:
即根据差异的输入参数来构建SqlSessionFactory这个工厂对象。
2.工厂模式
在Mybatis中好比SqlSessionFactory利用的是工厂模式,该工厂没有那么复杂的逻辑,是一个简朴工厂模式。
简朴工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简朴工厂模式中,可以根据参数的差异返回差异类的实例。简朴工厂模式专门界说一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
11.png SqlSession可以以为是一个Mybatis工作的焦点的接口,通过这个接口可以实行实行SQL语句、获取Mappers、管理事件。雷同于连接MySQL的Connection对象。
12.png 可以看到,该Factory的openSession方法重载了许多个,分别支持autoCommit、Executor、Transaction等参数的输入,来构建焦点的SqlSession对象。
在DefaultSqlSessionFactory的默认工厂实现里,有一个方法可以看出工厂怎么产出一个产物:
13.png 这是一个openSession调用的底层方法,该方法先从configuration读取对应的情况设置,然后初始化TransactionFactory得到一个Transaction对象,然后通过Transaction获取一个Executor对象,末了通过configuration、Executor、是否autoCommit三个参数构建了SqlSession。
在这里其实也可以看到端倪,SqlSession的实行,其实是委托给对应的Executor来举行的。而对于LogFactory,它的实当代码:
这里有个特别的地方,是Log变量的的范例是Constructor<extends Log>,也就是说该工厂生产的不但是一个产物,而是具有Log公共接口的一系列产物,好比Log4jImpl、Slf4jImpl等许多具体的Log。
3.单例模式
单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个体系提供这个实例,这个类称为单例类,它提供全局访问的方法。
单例模式的要点有三个:
一是某个类只能有一个实例;
二是它必须自行创建这个实例;
三是它必须自行向整个体系提供这个实例。
单例模式是一种对象创建型模式,单例模式又名单件模式或单态模式。
15.png 在Mybatis中有两个地方用到单例模式,ErrorContext和LogFactory,此中ErrorContext是用在每个线程范围内的单例,用于记录该线程的实行情况错误信息,而LogFactory则是提供给整个Mybatis利用的日志工厂,用于得到针对项目设置好的日志对象。
ErrorContext的单例实当代码:
构造函数是private修饰,具有一个static的局部instance变量和一个获取instance变量的方法,在获取实例的方法中,先判定是否为空如果是的话就先创建,然后返回构造好的对象。
只是这里有个风趣的地方是,LOCAL的静态实例变量利用了ThreadLocal修饰,也就是说它属于每个线程各自的数据,而在instance()方法中,先获取本线程的该实例,如果没有就创建该线程独有的ErrorContext。
4.署理模式
署理模式可以以为是Mybatis的焦点利用的模式,正是由于这个模式,我们只须要编写Mapper.java接口,不须要实现,由Mybatis配景帮我们完成具体SQL的实行。
署理模式(Proxy Pattern) :给某一个对象提供一个署理,并由署理对象控制对原对象的引用。署理模式的英文叫做Proxy或Surrogate,它是一种对象布局型模式。
署理模式包罗如下脚色:
1) Subject: 抽象主题脚色
2) Proxy: 署理主题脚色
3) RealSubject: 真实主题脚色
17.png 18.png 这里有两个步调,第一个是提前创建一个Proxy,第二个是利用的时间会主动请求Proxy,然后由Proxy来实行具体事件。
当我们利用Configuration的getMapper方法时,会调用mapperRegistry.getMapper方法,而该方法又会调用mapperProxyFactory.newInstance(sqlSession)来天生一个具体的署理:
在这里,先通过T newInstance(SqlSession sqlSession)方法会得到一个MapperProxy对象,然后调用                    T newInstance(MapperProxy mapperProxy)天生署理对象然后返回。
而检察MapperProxy的代码,可以看到如下内容:
非常典型的,该MapperProxy类实现了InvocationHandler接口,而且实现了该接口的invoke方法。
通过这种方式,我们只须要编写Mapper.java接口类,认真正实行一个Mapper接口的时间,就会转发给MapperProxy.invoke方法,而该方法则会调用后续的sqlSession.cud<executor.execute>prepareStatement等一系列方法,完成SQL的实行和返回。
5.组合模式
组合模式组合多个对象形成树形布局以表现“团体-部分”的布局条理。
组合模式对单个对象(叶子对象)和组合对象(组合对象)具有同等性,它将对象构造到树布局中,可以用来形貌团体与部分的关系。同时它也含糊了简朴元素(叶子对象)和复杂元素(容器对象)的概念,使得客户可以大概像处理惩罚简朴元素一样来处理惩罚复杂元素,从而使客户步调可以大概与复杂元素的内部布局解耦。
在利用组合模式中须要留意一点也是组合模式最关键的地方:叶子对象和组合对象实现雷同的接口。这就是组合模式可以大概将叶子节点和对象节点举行同等处理惩罚的原因。
Mybatis支持动态SQL的强盛功能,好比下面的这个SQL:
XHTML
在这内里利用到了trim、if等动态元素,可以根据条件来天生差异情况下的SQL;
在DynamicSqlSource.getBoundSql方法里,调用了rootSqlNode.apply(context)方法,apply方法是全部的动态节点都实现的接口:
对于实现该SqlNode接口的全部节点,就是整个组合模式树的各个节点:
24.png 组合模式的简朴之处在于,全部的子节点都是同一类节点,可以递归的向下实行,好比对于TextSqlNode,由于它是最底层的叶子节点,以是直接将对应的内容append到SQL语句中:
25.png 6.模板方法模式
模板方法模式是全部模式中最为常见的几个模式之一,是基于继承的代码复用的根本技能。
模板方法模式须要开发抽象类和具体子类的计划师之间的协作。一个计划师负责给出一个算法的外貌和骨架,另一些计划师则负责给出这个算法的各个逻辑步调。
代表这些具体逻辑步调的方法称做根本方法(primitive method);而将这些根本方法汇总起来的方法叫做模板方法(template method),这个计划模式的名字就是以后而来。
模板类界说一个利用中的算法的骨架,而将一些步调延长到子类中。使得子类可以不改变一个算法的布局即可重界说该算法的某些特定步调。
26.png 在Mybatis中,sqlSession的SQL实行,都是委托给Executor实现的,Executor包罗以下布局:
此中的BaseExecutor就采取了模板方法模式,它实现了大部分的SQL实行逻辑,然后把以下几个方法交给子类定制化完成:
该模板方法类有几个子类的具体实现,利用了差异的策略:
1) 简朴SimpleExecutor:每实行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。(可以是Statement或PrepareStatement对象)
2) 重用ReuseExecutor:实行update或select,以sql作为key查找Statement对象,存在就利用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次利用。(可以是Statement或PrepareStatement对象)
3) 批量BatchExecutor:实行update(没有select,JDBC批处理惩罚不支持select),将全部sql都添加到批处理惩罚中(addBatch()),等候同一实行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等候逐一实行executeBatch()批处理惩罚的;BatchExecutor相称于维护了多个桶,每个桶里都装了许多属于本身的SQL,就像苹果蓝里装了许多苹果,番茄蓝里装了许多番茄,末了,再同一倒进堆栈。(可以是Statement或PrepareStatement对象)
好比在SimpleExecutor中如许实现update方法:
7.适配器模式
适配器模式(Adapter Pattern) :将一个接口转换成客户渴望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为适配器(Adapter )。适配器模式既可以作为类布局型模式,也可以作为对象布局型模式。
30.png 在Mybatsi的logging包中,有一个Log接口:
31.png 该接口界说了Mybatis直接利用的日志方法,而Log接口具体由谁来实现呢?Mybatis提供了多种日志框架的实现,这些实现都匹配这个Log接口所界说的接口方法,终极实现了全部外部日志框架到Mybatis日志包的适配:
好比对于Log4jImpl的实现来说,该实现持有了org.apache.log4j.Logger的实例,然后全部的日志方法,均委托该实例来实现。
8.装饰者模式
装饰模式(Decorator Pattern) :动态地给一个对象增长一些额外的职责(Responsibility),就增长对象功能来说,装饰模式比天生子类实现更为机动。其别名也可以称为包装器(Wrapper、Decorator)。根据翻译的差异,装饰模式也有人称之为“油漆工模式”,它是一种对象布局型模式。
1) 不改变原类文件
2)  不利用继承
3)  动态扩展
在mybatis中,缓存的功能由根接口Cache(org.apache.ibatis.cache.Cache)界说。整个体系采取装饰器计划模式,数据存储和缓存的根本功能由PerpetualCache(org.apache.ibatis.cache.impl.PerpetualCache)永世缓存实现,然后通过一系列的装饰器来对PerpetualCache永世缓存举行缓存策略等方便的控制。如下图:
35.png 用于装饰PerpetualCache的标准装饰器共有8个(全部在org.apache.ibatis.cache.decorators包中):
FifoCache:先辈先出算法,缓存接纳策略
LoggingCache:输出缓存掷中的日志信息
LruCache:近来最少利用算法,缓存接纳策略
ScheduledCache:调理缓存,负责定时清空缓存
SerializedCache:缓存序列化和反序列化存储
SoftCache:基于软引用实现的缓存管理策略
SynchronizedCache:同步的缓存装饰器,用于防止多线程并发访问
WeakCache:基于弱引用实现的缓存管理策略
别的,尚有一个特别的装饰器TransactionalCache:事件性的缓存
正如大多数恒久层框架一样,mybatis缓存同样分为一级缓存和二级缓存:
一级缓存,又叫当地缓存,是PerpetualCache范例的永世缓存,生存在实行器中(BaseExecutor),而实行器又在SqlSession(DefaultSqlSession)中,以是一级缓存的生命周期与SqlSession是雷同的。
二级缓存,又叫自界说缓存,实现了Cache接口的类都可以作为二级缓存,以是可设置如encache等的第三方缓存。二级缓存以namespace名称空间为其唯一标识,被生存在Configuration焦点设置对象中。
二级缓存对象的默认范例为PerpetualCache,如果设置的缓存是默认范例,则mybatis会根据设置主动追加一系列装饰器。
Cache对象之间的引用序次为:
SynchronizedCache–>LoggingCache–>SerializedCache–>ScheduledCache–>LruCache–>erpetualCache
9.迭代器模式
迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的界说为:提供一种方法访问一个容器(container)对象中各个元素,而又不需袒露该对象的内部细节。
Java的Iterator就是迭代器模式的接口,只要实现了该接口,就相称于应用了迭代器模式:
好比Mybatis的PropertyTokenizer是property包中的重量级类,该类会被reflection包中其他的类频仍的引用到。这个类实现了Iterator接口,在利用时常常被用到的是Iterator接口中的hasNext这个函数。
可以看到,这个类传入一个字符串到构造函数,然后提供了iterator方法对分析后的子串举行遍历,是一个很常用的方法类。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-21 19:32, Processed in 0.176739 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表