MyBatis原理解析

目录

目标

启动过程

执行过程

主要类的生命周期和应用范围


1. 目标

通过本篇文章,你可以如下问题的答案。springboot启动过程中,mybatis都做了什么?执行具体方法时,mybatis都做了什么?

2. 启动过程

只要是能和spring进行组合第三方中间件,都是针对spring扩展点进行个性化实现。关于mybatis的启动过程,需要先了解springboot的启动流程,如果还不了解,请前往另一篇文章

2.1. 启动过程经历的几个流程

2.2. 对每个流程进行概述

2.2.1. beanfactory生命周期扩展,扫描mapper接口并注册到工厂

在beanFactoryPostProcessor回调时
依据MapperScan配置,扫描生成mapper接口的BeanDefinition,每个BeanDifinition的beanClass均设置为org.mybatis.spring.mapper.MapperFactoryBean,作为真正待实例化的类,然后注册到beanfactory。

org.mybatis.spring.annotation.MapperScannerRegistrar#registerBeanDefinitions
org.mybatis.spring.mapper.ClassPathMapperScanner

2.2.2. beanfactory生命周期扩展,autoConfig自定义

mybatis包中spring.factories配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

autoconfig会在scan过程执行后执行,即所有用户定义的bean都注册到工厂后执行。

mybatis检查mapper xml资源是否存在,生成SqlSessionFactory和SqlSessionTemplate

2.2.3. bean生命周期扩展,匹配解析xml与配置

在beanPostProcessor.after回调时匹配解析对应的xml

org.springframework.dao.support.DaoSupport#afterPropertiesSet
org.mybatis.spring.mapper.MapperFactoryBean#checkDaoConfig
org.apache.ibatis.binding.MapperRegistry#addMapper
org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parse

匹配mapper.xml:mapper类全路径.replace('.', '/') + ".xml"

解析xml:每个method生成一个methodStatement,主要是通过注解添加的配置,如cache配置

2.2.4. bean生命周期扩展,生成mapperProxy 

在beanPostProcessor.after回调时每个mapper实例生成一个mapperProxy
org.apache.ibatis.binding.MapperProxy

mapper接口引用
org.apache.ibatis.binding.MapperProxy#mapperInterface

mapper接口中定义的方法与mapper.xml配置关系
org.apache.ibatis.binding.MapperProxy#methodCache

3. 执行过程

通过参数解析器、执行器,执行具体mapper method。具体流程如下:

mapperProxy找到对应的或生成新的mapperMethod,涉及解析方法签名,如返回类型、定义的入参等
mapperMethod根据sql类型选择处理策略,即insert\update\delete\select,以select为例

组织入参,放于map中。

map-key包括:

  • based-0 index,如0、1...
  • 注解定义的参数名
  • paramNum,如param1\param2...
调用sqlSession实例(如sqlSessionTemplate)对应方法,如selectList
委派给DefaultSqlSession#selectList
委派给执行器#query
拦截器intercepter,可以修改sql,如分页处理、数据隔离等
实际获取数据,使用cache或从数据库查询
结果处理,根据定义的返回值类型,决定直接返回,或组织为数组或集合。

MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。

3.1. 执行mapper具体方法

org.apache.ibatis.binding.MapperMethod#execute

3.2. 参数解析器

 根据xml配置参数与当前参数生成参数关系

3.3. 执行器执行

 根据之前解析的xml配置与当前参数生成变量绑定的sql(org.apache.ibatis.mapping.MappedStatement#getBoundSql)
 若使用cache则从cache取结果并返回
 不使用cache或cache未命中则执行sql

3.4. 结果转换

4. 主要类的生命周期和应用范围

MyBatis中常用的类就要数SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、SqlMapper了。那么下面对他们的应用范围和生命周期进行一下说明:

SqlSessionFactoryBuilder在应用中该类实例的主要作用是创建SqlSessionFactory实例,故任务完成后就可以消失了。因此该类实例的最佳应用范围和生命周期应为“方法范围”。
SqlSessionFactory在应用的整个周期中会有众多地方需要利用其实例打开某个SqlSession,因此最佳范围是“应用生命周期范围”。故此,可以使用单例与工厂模式,在官方文档中最佳建议是IoC容器,如Spring来生成该实例。
SqlSession该类是非线程安全的,其实例是不能共享的,所以应该每个线程具有自己的SqlSession实例。因此最佳建议是“请求或方法范围”。例如:收到一个Http请求后,创建一个实例,进行某些操作,之后关闭。确保将关闭放于finally中。
SqlMapper是创建绑定映射语句的接口。其实例从SqlSession获得,所以其最宽生命周期与SqlSession相同,因此其实例的执行范围也是“方法范围”,而且其不需要明确的关闭。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值