Mybatis源码分析(1)

1、Maven

OGNL的三要素

表达式:OGNL表达式是功能强大的表达式语言,何解?在ognl中想要执行取值,赋值,调用方法等等操作,你都需要用表达式表示。通过表达式,底层会解析出来你的想要操作。它支持链式结构

根对象:即root对象,可以理解为OGNL的操作对象,表达式规定做什么,而该对象就指定对谁操作。OGNL叫做对象图导航语言,对象图就是以任意一个对象作为根,通过OGNL可以访问到与这个对象相关的其他对象。底层使用list集合做的。

Context对象:其实就是OGNL的上下文环境。root对象也在OGNL的上下文环境里,底层是一个Map集合。该上下文环境规定了OGNL操作在”哪里进行”,注意访问context对象时候需要在表达式中加上#。

Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态”AOP”框架。

核心内容如下:

基于类的动态代理

_Hsqldb_是一个开放源代码的JAVA数据库,其具有标准的SQL语法和JAVA接口,它可以自由使用和分发,非常简洁和快速的

Apache _Derby_是一个完全用java编写的数据库

_H2_是一个短小精干的嵌入式数据库引擎,主要的特性包括: 免费、开源、快速 嵌入式的数据库服务器,支持集群 提供JDBC、ODBC访问接口

什么是Mockito

Mockito是一个非常优秀的模拟框架,可以使用它简洁的API来编写漂亮的测试代码,它的测试代码可读性高同时会产生清晰的错误日志。

Velocity是一个基于Java的模板引擎,可以通过特定的语法获取在java对象的数据 , 填充到模板中,从而实现界面和java代码的分离!

_PostgreSQL_是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS)

java连接mysql数据库

MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一

2、从哪里开始?

用于通过字节流|字符流构建 SqlSessionFactory

内部构建过程:

  • 通过流获取相应的 XMLConfigBuilder
  • XMLConfigBuilder解析返回 Configuration
  • 根据配置构建出 SqlSessionFactory
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
  try {
    XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
    return build(parser.parse());
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  } finally {
    ErrorContext.instance().reset();
    try {
     if (reader != null) {
       reader.close();
     }
    } catch (IOException e) {
      // Intentionally ignore. Prefer previous error.

    }
  }
}

这个类可以被实例化、使用和丢弃, 一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但 最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情

通过一些配置去创建SqlSession,例如:autoCommit|Connection|TransactionIsolationLevel|ExecutorType

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

使用 MyBatis 的主要 Java 接口。通过此接口,您可以执行命令、获取映射器和管理事务

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。

// 以下非全部方法,只是作为举例
public interface SqlSession extends Closeable {
         T selectOne(String statement, Object parameter);
       List selectList(String statement, Object parameter);
       List selectList(String statement, Object parameter, RowBounds rowBounds);
         Map selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
       Cursor selectCursor(String statement, Object parameter, RowBounds rowBounds);
      void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
      int insert(String statement, Object parameter);
      int update(String statement, Object parameter);
      int delete(String statement, Object parameter);
      void commit(boolean force);
      void rollback(boolean force);
       T getMapper(Class type);
      Connection getConnection();
}

绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession,如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:

try (SqlSession session = sqlSessionFactory.openSession()) {
  // 你的应用逻辑代码
}

所有代码中都遵循这种使用模式,可以保证所有数据库资源都能被正确地关闭。

3、缓存

Cache:缓存的顶级接口,定义了缓存的增删改查、获取大小,id等行为

PerpetualCache:在MyBatis里面,它是一级缓存、二级缓存的最基本实现 (详细参见),一下是所有特性的缓存模式均在包: org.apache.ibatis.cache.decorators下:

BlockingCache:读阻塞缓存,对应的key没有被缓存的话,将会 阻塞所有需要获取该key数据(也可以设定超时时间) 的线程,直到有其他线程在缓存中设置该key数据后,阻塞线程将继续执行后续

FifoCache:固定大小队列缓存,维护了一个队列,可以设置队列大小(默认1024个位置),如果新进来一个key值,使得缓存集合中长度大于设定的长度,则将根据先进先出(first in, first out)原则,删除最先进来的key-value键值对儿,此队列只与put方法超过长度时有关,删除缓存元素不影响队列中的元素

LoggingCache:记录缓存命中率日志缓存,获取缓存的命中率日志(命中缓存key的个数与请求缓存总数的比率)

LruCache:最近最少使用的缓存,内部维护了一个LinkedHashMap,通过removeEldestEntry方法找到最近最老的key进行删除

ScheduledCache:定时清空缓存,在增删改查入口做了校验,该校验用于检查定时时间是否超过设定预期时间,超过则清空缓存数据

SerializedCache:序列化缓存,将key对应的value值以对象流的形式存于缓存中

SoftCache:软引用缓存,每次操作都会对应的将原来已被垃圾收集器收集过的对象数据删除,put操作会put一个软引用数据缓存

SynchronizedCache:同步缓存,内部几乎所有方法均加锁,是一个线程安全的缓存

TransactionalCache:事务性缓存,内部有两个方法,commiit以及rollback,在没有commit之前将所有key-value键值对临时存于一个内部map中,commit之后,将临时map以及get的时候的key空数据存储与真正的缓存中

WeakCache:若引用缓存,没什么可解释的

让每一种特性的缓存都实现了事务的功能

内部维护了一个map

private final Map transactionalCaches = new HashMap<>();

put是为传入的类型的缓存设置数据,在commit提交方法时,对每中特性缓存实例中的数据轮循做一次提交

public void putObject(Cache cache, CacheKey key, Object value) {
  getTransactionalCache(cache).putObject(key, value);
}
private TransactionalCache getTransactionalCache(Cache cache) {
    return transactionalCaches.computeIfAbsent(cache, TransactionalCache::new);
}
public void commit() {
    for (TransactionalCache txCache : transactionalCaches.values()) {
      txCache.commit();
    }
}
public void rollback() {
    for (TransactionalCache txCache : transactionalCaches.values()) {
      txCache.rollback();
    }
}

构造缓存用的,内部维护了一个 implementation(默认是:PerpetualCache), decorators(默认只有一个LruCache)

public class CacheBuilder {
  private final String id;
  private Class implementation; // 构造缓存时,基于该缓存实例构造的(将该缓存类型传入所有装饰者的构造函数中)
  private final List> decorators;// 缓存类型的集合
  private Integer size;// 设置缓存大小(像fifo缓存以及Lru算法缓存需要根据size这个去判断是否需要删除元素)
  private Long clearInterval; // 设置清理间隔(如果有定时清空类型的缓存时)
  private boolean readWrite; // 暂时没有用到,Cache顶级类中有一个获取读写锁的方法,可能与这个有关
  private Properties properties;// 根据这个属性去填充各个类型缓存的字段数据
  private boolean blocking;// 是否阻塞(阻塞式缓存用到的)

  public CacheBuilder(String id) {
    this.id = id;
    this.decorators = new ArrayList<>();
  }
}

总结:这里Mybatis在缓存的设计上用了装饰器模式、抽象工厂模式

Original: https://www.cnblogs.com/lishanbiaosMark/p/16344093.html
Author: 码出新生活!
Title: Mybatis源码分析(1)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/579720/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux基操

    1 解压命令:tar -zxcf [压缩包名] 2 &…

    Java 2023年6月8日
    088
  • 记录一下今天所学 9.22

    今天上午在公司没啥任务,就学起了es,看的黑马的资料,先看文档,不懂的地方就去看了下视频。 大概知道了es概念,es是es技术栈中最核心的,这个技术栈还有其他的比如分词器插件,还有…

    Java 2023年6月15日
    080
  • java package(包)的用法

    一般来说都用eclipse自动化图形工具搞定,我用的是ubuntu,所以需要自己打包引入。 什么是包? 这是对java源代码的组织和管理的一种方式,比如:当操作系统某个目录的文件非…

    Java 2023年5月29日
    095
  • Springboot&&LinuX

    一、现学习规划 Springboot 概念介绍:全新框架,简化Spring应用的初始搭建以及开发过程 Springboot核心:自动装配 微服务阶段 javase:OOP mysq…

    Java 2023年6月8日
    075
  • Dijkstra在路由选择中的应用

    Dijkstra在路由选择中的应用 前言背景 OSPF协议(Open Shortest Path First,开放最短路径优先)是在1989年由互联网工程任务组(IETF)正式发布…

    Java 2023年6月16日
    081
  • Maven使用总结

    Maven使用总结 一、Maven的主要作用 Maven 翻译为”专家”、”内行”,是 Apache 下的一个纯 Java 开发的开…

    Java 2023年6月8日
    0101
  • 设计模式学习笔记(十六)迭代器模式及其在Java 容器中的应用

    迭代器(Iterator)模式,也叫做游标(Cursor)模式。我们知道,在Java 容器中,为了提高容器遍历的方便性,我们利用迭代器把遍历逻辑从不同类型的集合类中抽取出来,从而避…

    Java 2023年6月6日
    093
  • Java之取余操作 “%”

    取模运算与取余运算两个概念有重叠的部分但又不完全一致。主要的区别在于对负整数进行除法运算时操作不同。 对于整形数a,b来说,取模运算或者求余运算的方法都是: 1、求 整数商 c =…

    Java 2023年6月6日
    069
  • Spring学习记录

    1.IOC控制翻转 英文全称 Inversion of control,还有个名称叫依赖注入 Dependency injection ,Spring框架核心容器就是基于这个反向控…

    Java 2023年5月30日
    093
  • 每日一问:讲讲 Java 虚拟机的垃圾回收

    昨天我们用比较精简的文字讲了 Java 虚拟机结构,没看过的可以直接从这里查看: 今天我们必须来看看 Java 虚拟机的垃圾回收算法是怎样的。不过在开始之前,我们一定得确定哪些是活…

    Java 2023年5月29日
    090
  • Nginx中的rewrite指令(break,last,redirect,permanent)

    在server块下,会优先执行rewrite部分,然后才会去匹配location块 server中的rewrite break和last没什么区别,都会去匹配location,所以…

    Java 2023年5月30日
    088
  • netty+springboot+oracle+protobuf 搭建客户端服务端

    netty5已经不维护了,所以用netty4搭建项目 一、创建俩个基础的springboot项目 分别为netty-client和netty-server 二、添加依赖 客户端 x…

    Java 2023年5月30日
    097
  • js移除style样式

    removeAttribute() 例: 保存 let btnadd=document.getElementById("btnadd");btnadd.remo…

    Java 2023年6月15日
    080
  • spring boot2整合shiro安全框架实现前后端分离的JWT token登录验证

    https://blog.csdn.net/wozniakzhang/article/details/95855296?utm_medium=distribute.pc_relev…

    Java 2023年5月30日
    099
  • Java学习-087-自定义MANIFEST.MF 文件并打包生效

    在 src/main/resources 文件夹下创建 MANIFEST.MF 文件,文件内容如下所示: Created-By: 范丰平 Manifest-Version: 1.0…

    Java 2023年5月29日
    085
  • rose-jade自动生成dao、model

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/FCWORLD/p/5371923.htmlAuthor…

    Java 2023年6月6日
    064
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球