mybatis原理分析

1、mybatis实现的相关思考

    如果要实现mybatis的功能,我应该会怎么做?

  1. 读取和解析配置文件,包含mapping.xml
  2. 根据配置获取数据源( JDBC操作)
  3. 执行配置或者注解的sql,将结果集,封装对象返回

思考: mybatis中dao层只有接口,如果获取到实现类?

2、源码分析

  1. 通过SqlSessionFactoryBuilder 使用XMLConfigBuilder解析配置文件
  2. 将解析的数据库放入Configuration对象中
  3. 通过Configuration获取到DefaultSqlSessionFactory
  4. 再获取SqlSession(接口中底层封装增删改查的方法,自带一级缓存,底层HashMap)
  5. 创建session实例.openSession();详见【1】
  6. 通过代理设计模式获取到MapperProxy,执行目标方法(JDK动态代理)

注: 

(1)将配置文件中的mappers存放到configuration的mapperRegistry中

(2)数据库配置放在Environment中的DataSource中

(3)Configuration对象中的部分属性:

MapperRegistry:存放dao层接口

loadedResources:需要加载的类或者文件

【1】创建的openSession源码分析:
1、创建事务管理器
2、默认创建SimpleExecutor执行器 ,将简单执行器丢给 缓存执行器CachingExecutor(通过构造函数传递。由于默认开启了二级缓存,如果没有二级缓存配置,仍然执行的是SimpleExecutor)最后丢给DefaultSqlSession

在同一个sqlSession缓存为了防止脏数据,增加、修改、删除的时候 都会清除所有本地一级缓存。具体方法:org.apache.ibatis.executor.BaseExecutor#clearLocalCache

mybatis一级缓存无法禁用,存在线程安全,以及集群环境中的读取脏数据的问题。(原因:每个一个缓存都是存在HashMap,本地自带的JVM中,另一JVM操作了同一条数据,无法清空其他JVM的一级缓存)。

只用调用.clearCache();或者每次使用新的sqlSession来防止这个缓存问题。

事情上,整合springboot时,每次controller调用都会重新创建sqlSession,因此不存在一级缓存的问题。可以理解此时的一级缓存就是一个线程变量ThreadLocal,只对当前线程的查询的sql结果进行缓存。

mybatis开启二级缓存:

二级缓存回收策略

 1、LRU:最近最少使用的策略,移除最长时间不被使用的对象。

 2、FIFO:先进先出策略,按对象进入缓存的顺序来移除它们。

 3、SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象。

 4、WEAK:弱引用策略,更积极地移除基于垃圾收集器状态和弱引用规则的对象。

 注:软引用与弱引用的区别:

  (1)软引用: 软引用是用来描述一些有用但并不是必需的对象, 对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象

  (2)弱引用: 弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象

 

联想一下:redis-缓存失效三种策略(FIFO 、LRU、LFU)

当缓存需要被清理时(比如空间占用已经接近临界值了),需要使用某种淘汰算法来决定清理掉哪些数据。常用的淘汰算法有下面几种:

  1. FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。
  2. LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。
  3. LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。

 

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;

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值