0%

注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 官方文档中阅读本系列文章。

1.服务导出过程

本篇文章,我们来研究一下 Dubbo 导出服务的过程。Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑。整个逻辑大致可分为三个部分,第一是前置工作,主要用于检查参数,组装 URL。第二是导出服务,包含导出服务到本地 (JVM),和导出服务到远程两个过程。第三是向注册中心注册服务,用于服务发现。本篇文章将会对这三个部分代码进行详细的分析,在分析之前,我们先来了解一下服务的导出过程。

阅读全文 »

注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 官方文档中阅读本系列文章。

1.原理

我在上一篇文章中分析了 Dubbo 的 SPI 机制,Dubbo SPI 是 Dubbo 框架的核心。Dubbo 中的很多拓展都是通过 SPI 机制进行加载的,比如 Protocol、Cluster、LoadBalance 等。有时,有些拓展并非想在框架启动阶段被加载,而是希望在拓展方法被调用时,根据运行时参数进行加载。这听起来有些矛盾。拓展未被加载,那么拓展方法就无法被调用(静态方法除外)。拓展方法未被调用,就无法进行加载,这似乎是个死结。不过好在也有相应的解决办法,通过代理模式就可以解决这个问题,这里我们将具有代理功能的拓展称之为自适应拓展。Dubbo 并未直接通过代理模式实现自适应拓展,而是代理代理模式基础上,封装了一个更炫的实现方式。Dubbo 首先会为拓展接口生成具有代理功能的代码,然后通过 javassist 或 jdk 编译这段代码,得到 Class 类,最后在通过反射创建代理类。整个过程比较复杂、炫丽。如此复杂的过程最终的目的是为拓展生成代理对象,但实际上每个代理对象的代理逻辑基本一致,均是从 URL 中获取欲加载实现类的名称。因此,我们完全可以把代理逻辑抽出来,并通过动态代理的方式实现自适应拓展。这样做的好处显而易见,方便维护,也方便源码学习者学习和调试代码。本文将在随后实现一个动态代理版的自适应拓展,有兴趣的同学可以继续往下读。

阅读全文 »

注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 官方文档中阅读本系列文章。

1.简介

SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口加载实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。如果大家想要学习 Dubbo 的源码,SPI 机制务必弄懂。下面,我们先来了解一下 Java SPI 与 Dubbo SPI 的使用方法,然后再来分析 Dubbo SPI 的源码。

阅读全文 »

1.简介

我从七月份开始阅读MyBatis源码,并在随后的40天内陆续更新了7篇文章。起初,我只是打算通过博客的形式进行分享。但在写作的过程中,发现要分析的代码太多,以至于文章篇幅特别大。在这7篇文章中,有4篇文章字数超过了1万,最长的一篇文章约有2.7万字(含代码)。考虑到超长文章对读者不太友好,以及拆分文章工作量也不小等问题。遂决定将博文整理成电子书,方便大家阅读。

经过两周紧张的排版,《一本小小的MyBatis源码分析书》诞生了。本书共7章,约300页。本书以电子书的形式发布,大家可自由的下载。下载地址如下:

百度网盘:点击下载

测试代码:GitHub

下面来看看本书章节的缩略图。

hy

阅读全文 »

1.简介

一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展。这样的好处是显而易见的,一是增加了框架的灵活性。二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作。以 MyBatis 为例,我们可基于 MyBatis 插件机制实现分页、分表,监控等功能。由于插件和业务无关,业务也无法感知插件的存在。因此可以无感植入插件,在无形中增强功能。

阅读全文 »

1.简介

在 Web 应用中,缓存是必不可少的组件。通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力。作为一个重要的组件,MyBatis 自然也在内部提供了相应的支持。通过在框架层面增加缓存功能,可减轻数据库的压力,同时又可以提升查询速度,可谓一举两得。MyBatis 缓存结构由一级缓存和二级缓存构成,这两级缓存均是使用 Cache 接口的实现类。因此,在接下里的章节中,我将首先会向大家介绍 Cache 几种实现类的源码,然后再分析一级和二级缓存的实现。下面先来分析 Cache 及其实现类。

阅读全文 »

1.简介

本篇文章将向大家介绍 MyBatis 内置数据源的实现逻辑。搞懂这些数据源的实现,可使大家对数据源有更深入的认识。同时在配置这些数据源时,也会更清楚每种属性的意义和用途。因此,如果大家想知其然,也知其所以然。那么接下来就让我们一起去探索 MyBatis 内置数据源的源码吧。

MyBatis 支持三种数据源配置,分别为 UNPOOLED、POOLED 和 JNDI。并提供了两种数据源实现,分别是 UnpooledDataSource 和 PooledDataSource。在三种数据源配置中,UNPOOLED 和 POOLED 是我们最常用的两种配置。至于 JNDI,MyBatis 提供这种数据源的目的是为了让其能够运行在 EJB 或应用服务器等容器中,这一点官方文档中有所说明。由于 JNDI 数据源在日常开发中使用甚少,因此,本篇文章不打算分析 JNDI 数据源相关实现。大家若有兴趣,可自行分析。接下来,本文将重点分析 UNPOOLED 和 POOLED 两种数据源。其他的就不多说了,进入正题吧。

阅读全文 »

* 本文速览

本篇文章较为详细的介绍了 MyBatis 执行 SQL 的过程。该过程本身比较复杂,牵涉到的技术点比较多。包括但不限于 Mapper 接口代理类的生成、接口方法的解析、SQL 语句的解析、运行时参数的绑定、查询结果自动映射、延迟加载等。本文对所列举的技术点,以及部分未列举的技术点都做了较为详细的分析。全文篇幅很大,需要大家耐心阅读。下面来看一下本文的目录:

源码分析类文章通常比较枯燥。因此,我在分析源码的过程中写了一些示例,同时也绘制了一些图片。希望通过这些示例和图片,帮助大家理解 MyBatis 的源码。

阅读全文 »

1.简介

在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程。由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因。所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来,独立成文,于是就有了本篇文章。在本篇文章中,我将分析映射文件中出现的一些及节点,比如 <cache>,<cache-ref>,<resultMap>, <select | insert | update | delete> 等。除了分析常规的 XML 解析过程外,我还会向大家介绍 Mapper 接口的绑定过程等。综上所述,本篇文章内容会比较丰富,如果大家对此感兴趣,不妨花点时间读一读,会有新的收获。当然,本篇文章通篇是关于源码分析的,所以阅读本文需要大家对 MyBatis 有一定的了解。如果大家对 MyBatis 还不是很了解,建议阅读一下 MyBatis 的官方文档

阅读全文 »

* 本文速览

由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括。本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settingstypeAliasestypeHandlers等,本文的篇幅也主要在对这三个配置解析过程的分析上。下面,我们来一起看一下本篇文章的目录结构。

从目录上可以看出,2.3节、2.5节和2.8节的内容比较多。其中2.3节是关于settings配置解析过程的分析,除了对常规的 XML 解析过程分析,本节额外的分析了元信息类MetaClass源码的逻辑。2.5节则是详细分析了别名注册的过程,包含自动注册和手动注册别名等两种方式。2.8节则是详细介绍了类型处理器的注册过程,类型注册逻辑是封装在TypeHandlerRegistry类中的各个register重载方法中。由于重载方法比较多,且互为调用,调用关系比较复杂。为此,我专门画了一张方法调用关系图。这张图在分析类类型处理器注册那一块的源码时,会很有用。

阅读全文 »