万字博文,Spring系列之抽丝剥茧Spring源码(一)

2023-05-16

当5G来临,当211高校已经开启人工智能课程,当甲骨文大批量裁员,大家的心是否像我一样为之一颤呢?当科技不断发展,技术迅速迭代,程序员愈发年轻化的今天,而作为我们已经步入中年的程序员来说路在何方?当我们逐渐老去,我们不能指望企业家的怜悯,当大批年轻化的程序员涌入互联网大潮时,他们的思维,他们的体能,甚至他们的能力都远超于我们,我们又该何去何从?职场不相信眼泪,更不会同情,唯有修炼内功,修炼职场硬实力,当然如果硬实力不行,也只能来点软的了…

作为程序员不懂高并发、JVM优化、系统内核、大数据、框架源码… …,整天写CRUD,也许很快就会被时代所淘汰。

下面让我带你抽丝剥茧spring源码。会从spring ioc容器核心结构、spring ioc注入执行流程的脉络讲起,包括什么是BeanFactory和FactoryBean;什么是BeanDefinition及其有哪些重要的实现类;什么是BeanPostProcessor、BeanFactoryPostProcessor、ImportSelector、ImportBeanDefinitionRegistrar,以及如何应用他们来实现对spring的扩展等等,逐步深入细节,当然spring源码非常庞大难懂,本文是从spring ioc讲起,重点是梳理spring ioc注入的脉络,之后的博文会一点点抽丝剥茧的对spring内部处理细节做逐步分析讲解,包括Spring aop、spring Tx等等,来逐步解密spring。

带您初识spring容器模型

在这里插入图片描述
在学习spring ioc源码之前,有必要先了解下其核心类的含义及作用。上面是一个粗略的spring bean工厂内部存储,鉴于spring工厂比较庞大,上图也只画出了一部分比较重要的核心类,但是即便这样这个图片也已经看不清了,但是我会带您一个个讲解说明。

初始化spring容器测试代码:

在这里插入图片描述在这里插入图片描述

  • 首先既然是spring ioc,它的最重要的作用就是管理bean,所以我们猜测肯定是会有一个bean工厂的,这个是很多框架都有的(如mybatis),上来就会来个工厂。这就是 BeanFactory,在spring中默认的实现类为DefaultBeanFactory,DefaultBeanFactory作为bean工厂的默认实现,主要提供了bean的注册,bean的获取取。当然bean的注册和获取的具体实现是由其子类AbstractBeanFactory和DefaultSingletonBeanRegistry类完成。
    其实在本文开始的时候我也提到了FactoryBean,那么FactoryBean又是什么的?它是一个spring提供的一个接口,其实大家目前可以简单粗暴的理解为是一个特殊的bean,在某些 情况下bean的实例化过程比较复杂,可以实现FactoryBean接口重写getObject()方法来实现一个复杂bean的实例化,实现FactoryBean接口会在spring工厂中注入2个bean,实现 类本身会对应一个bean,beanName为&+类名(首字母小写),还有一个就是getObject()返回的bean,也就是我们自己自定义的bean,beanName为返回的Object类的类名 (首字母小写)。如我们比较熟悉的mybatis就是应用了spring的这个FactoryBean这个扩展类,具体mybatis中的哪个类应用了,大家自己想吧。

  • BeanDefinition:顾名思义,这个类是描述bean的接口。有两个重要的实现类分别是RootBeanDefinition和AnnotatedGenericBeanDefinition。RootBeanDefinition是用来定 义Spring内部的bean,如ConfigurationClassPostProcessor;AnnotatedGenericBeanDefinition是用来定义我们自定义的bean,也就是我们注入spring容器,需要spring管理的bean。

  • 说完BeanDefinition,我们来认识下bean的元数据定义类。ClassMetadata:定义类的元数据,其中包括getClassName、isInterface、isAnnotation方法;MethodMetadata:定义方法的元数据;AnnotationMetadata:定义注解类元数据信息;

  • Spring初始化时bean是怎么存储的?答案是存储在DefaultListableBeanFactory类的集合中,其中BeanDefinitionMap是存储了beanName和BeanDefinition的映射,beanDefinitionNames存储了beanName,见下图:

在这里插入图片描述
在这里插入图片描述
但请注意此时bean还没有实例化,实例化后,bean是存储在DefaultSingletonBeanRegistry类中的singletonObjects中,这个我们在之后分析源码的时候会详细说。

  • AnnotatedBeanDefinitionReader:这个类是spring容器初始化的时候,在DefaultListableBeanFactory初始化之后就会实例化的一个类。它主要的作用是向spring bean工厂中注册我们自定义的bean,但是这个类其实是委托了BeanDefinitionReaderUtils类去调用DefaultListableBeanFactory类去完成bean的注册的,可见DefaultListableBeanFactory的重要性。

  • BeanDefinitionHolder:封装了beanName和BeanDefinition,不用关注。

  • BeanFactoryPostProcessor:bean工厂的后置处理器,可以插手bean工厂初始化过程,实现这个接口会得到beanFactory实例,也就是可以操作bean工厂了。至于什么时候会执行其实现类,那是后面博文会讲解的内容。

  • BeanPostProcessor:bean的后置处理器。会插手bean实例化的过程,实现此接口可以操纵容器中正在初始化的bean,也就是说可以对bean属性做修改。

  • BeanDefinitionRegistryPostProcessor:是个接口,实现了BeanFactoryPostProcessor接口,定义了postProcessorBeanDefinitionRegistry(registry)方法,也就是扩展了BeanFactoryPostProcessor接口,spring内部ConfigurationClassPostProcessor类实现了这个接口,去完成bean的解析。

  • 实例化AnnotatedBeanDefinitionReader时,同时spring会向容器中注入7个spring自带的bean处理器。这些处理器在spring容器中都起着重要作用。这个也留待我们之后的博文中进行深入讲解。

  • ClassPathBeanDefinitionScanner:主要用于包的扫描工作。后续博文中会详细说。

    以上简要带大家认识了spring ioc注入过程中涉及到的一些比较重要的spring核心类。

Spring ioc初始化流程

在这里插入图片描述
下面我们就以注解方式初始化spring为例讲解下spring容器初始化过程。

Spring注解方式启动:实例化AnnotationConfigApplicationContext,传入需要扫描的配置类或需要注入的beanclass。接着我们就来进入主题,看下源码入口:
在这里插入图片描述

实例化父类构造方法

如上图,首先会执行其父类的构造方法,正如我这个方法上注释的说明,主要实例化三个类,我们分别看下:

GenericApplicationContext:主要实例化了beanFactory,默认为DefaultListableBeanFactory。
在这里插入图片描述

AbstractApplicationContext:主要实例化PathMatchingResourcePatternResolver。这个类我在第一部分没有拿出来说明,其实可以理解它是资源文件解析器,提供了解析资源文件的功能。
在这里插入图片描述

DefaultResourceLoader:实例化类加载器,其实就是APPClassLoader的实例。
在这里插入图片描述

执行完父类构造方法后,我们看下spring容器中的变化,即向spring容器中实例化了:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

无参构造方法

父类构造方法执行结束,我们就来看下主体方法中的第一个方法this()。它会调用无参的构造方法:
在这里插入图片描述
通过上面对代码的注解,你应该大致了解了这个构造方法做了什么。下面就在来看下里面的实现。
在这里插入图片描述
这个类最终主要会调用AnnotationConfigUtils.registerAnnotationConfigProcessors()方法,也就是AnnotatedBeanDefinitionReader会委托AnnotationConfigUtils类做一些事情,那么我们就看下registerAnnotationConfigProcessors()方法做了哪些事情。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
正如这段代码中我注释所写的那样,主要是向bean工厂中注册spring内部自定义的bean。其中这些bean有的是实现了BeanPostProcessor、BeanFactoryPostProcessor接口的,这两个接口我们在第一部分中做过说明。被注册的6个bean在后续的操作中都有着各自的作用,这些类会在后续的博文中做详细的介绍。

这里每个bean都会封装成RootBeanDefinition(这个我们在第一部分也做过说明,RootBeanDefinition是封装spring内部自定义的bean的),最终会调用registry.registerBeanDefinition(beanName, definition)方法向容器中注册bean。Registry其实就是DefaultListableBeanFactory的实例,那么也就是调用DefaultListableBeanFactory类的registerBeanDefinition()方法:
在这里插入图片描述
在这里插入图片描述
上面是当前会执行的代码部分,也就是会将那6个bean都注册到beanDefinitionMap中。这也就是实例化AnnotatedBeanDefinitionReader类主要做的事情。

我们在来看下现在spring容器中的变化,其实就是bean工厂中注册了7个spring自定义的bean:
在这里插入图片描述
在这里插入图片描述

上面说了构造函数中的this.reader = new AnnotatedBeanDefinitionReader(this)方法,接下来说下构造函数中ClassPathBeanDefinitionScanner实例化的过程。
在这里插入图片描述
其实这个实例化的过程比较简单,除了实例化ClassPathBeanDefinitionScanner类之外,主要就是注册了几个注解:
在这里插入图片描述
暂时可以先不用管这部分,不重要。
此时就完成了spring容器初始化的第一步,再让我们来看下spring容器目前的情况:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

register(annotatedClasses)注册自定义bean

接下来就要处理我们需要spring容器来管理的beanclass了。其实就是调用AnnotatedBeanDefinitionReader的register方法,其中参数AnnotatedClasses是我们传入的需要注入的bean,可以是一个带有@ComponentScan注解的配置类,也可以是一个bean集合,也可以是一个单个bean,所以此处做了循环操作处理。
在这里插入图片描述
最终会调用doRegisterBean()方法:

这个方法首先会调用shouldSkip()方法对beanclass做校验,具体校验逻辑见我对代码的注解说明:
在这里插入图片描述
接着会调用AnnotationConfigUtils.processCommonDefinitionAnnotations()方法,在这个方法中会给这个bean实例赋予属性,主要是通过这个beanclass上的注解来赋值,会看是否的@Lazy的、@Primary的值、@DependsOn的值、@Role的值、@Description的值,beanclass上存在这些注解就会取值并赋给bean实例。具体实现我们在之后的博文中会详细分析。
在这里插入图片描述
下面是这个方法中最重要的部分,也就是最终的注入。这个如下面第二个图所示,它最终也会调用registry.registerBeanDefinition()方法,也就是DefaultListableBeanFactory类的registerBeanDefinition()方法,最终将annotationClass注入到beanDefinitionMap和BeanDefinitionNames中。这个方法上面有说过,这里就不在说明了,这个方法中具体的细节会在之后的博文中详细分析。
在这里插入图片描述
在这里插入图片描述
至此我们的register()方法就处理脉络就说完了,我们在来看下此时的bean工厂的变化:
在这里插入图片描述
在这里插入图片描述
其实就是如我上面说的那样将annotationClass(App.class)注入到了我们的bean工厂中。

refresh()

上面主要说了spring ioc容器启动过程的前两个方法,下面我们来看下spring ioc容器启动的最核心最重要的方法refresh()。

下面就让我们看下refresh()方法都做了什么?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面是refresh()代码的主体部分,spring ioc容器初始化都会在这里完成,其内部代码非常复杂,这里我们就先了解下其处理脉络,看下每个方法都做了什么,在之后的博文中会详细讲解其处理细节。

prepareRefresh()

prepareRefresh():这个方法比较简单,主要是设置了启动时间、启动标识等操作,不是重点,先不用关注。

obtainFreshBeanFactory()

这个方法顾名思义,就是重新获取beanFactory实例,这个方法没有什么可说的,就是获取了之前我们初始化的beanFactory实例DefaultListableBeanFactory。
GenericApplicationContext:
在这里插入图片描述

prepareBeanFactory()

准备bean工厂初始化环境。主要是注入spring内部bean、注册Aware相关接口。

postProcessBeanFactory()

空方法。

invokeBeanFactoryPostProcessors()

这是比较重要的方法之一。其内部处理比较复杂,当然其处理方式是非常值得学习的,想要知道这个方法做了什么吗?下节我将带大家一起分析本方法和后续的处理方法的脉络部分。

最后

Spring的设计思想及源码不是一朝一夕能弄透的,需要长期的积累和思辨。我已开启Spring系列源码分析的教程,有兴趣的小伙伴请关注我。如果本文对您有价值,不要忘了点赞、留言。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

万字博文,Spring系列之抽丝剥茧Spring源码(一) 的相关文章

  • 【Linux应用编程】一个异步信号处理引起死锁问题的思考

    文章目录 1 前言2 为什么会产生死锁2 1 死锁2 2 分析2 3 结论 3 避免死锁4 举一反三5 死锁例子代码6 参考文章 1 前言 最近在维护别人的代码时 xff0c 遇到一个线程死锁问题 xff0c 一番折腾 xff0c 最终定位
  • 【RT-Thread】SGM706独立看门狗软件包

    文章目录 1 简介1 1 目录结构1 2 许可证 2 芯片介绍3 支持情况4 使用说明4 1 依赖4 2 获取软件包4 3 初始化4 4 启动看门狗4 5 msh finsh测试查看设备注册通过msh启动看门狗 5 注意事项6 联系方式 1
  • 利用tldr工具再也不怕记不住Linux命令

    文章目录 1 前言2 tldr3 安装4 使用 1 前言 linux命令非常多 xff0c 少用的命令往往易忘记 xff0c 甚至常用的语法较为复杂的命令也不好记住 当然有些太复杂的命令也不需要死记硬背 xff0c 我们往往会借助man命令
  • C++中的二阶构造函数

    文章目录 1 前言2 二阶构造3 总结 1 前言 构造函数用于创建对象时对象成员的初始化 xff0c 如赋初值 申请内存 加载文件等 xff0c 即是自动完成对象的初始化任务 在C 43 43 语言中 xff0c 构造函数执行顺序是 xff
  • open函数簇与fopen函数簇区别和用法

    文章目录 1 前言2 open与fopen区别2 1 标准不同2 2 层次不同2 3 适用对象不同 xff08 返回值不同 xff09 2 4 缓冲区2 5 效率不同 3 使用方法3 1 open3 2 fopen 1 前言 linux系统
  • 基于STM32的OLED多级菜单GUI实现(简化版智能手表)

    前言 xff1a 本文的OLED多级菜单UI 为一个综合性的STM32小项目 xff0c 使用多传感器 与OLED显示屏 实现智能终端 的效果 项目中的多级菜单UI使用了较为常见的结构体索引法 去实现功能与功能之间的来回切换 xff0c 搭
  • 【RTD】铂电阻测温原理与具体方法

    文章目录 1 基本原理2 铂电阻2 1 铂电阻测温原理2 2 铂电阻类型和测量方法2 2 1 两线式铂电阻2 2 2 三线式铂电阻2 2 3 四线式铂电阻 3 小结 相关文章 xff1a RTD 铂电阻测温原理与具体方法 RTD AD779
  • 【RTD】AD7793三线式铂电阻PT100/PT1000应用

    文章目录 1 AD7793简介2 AD7793 三线式铂电阻测量2 1 阻值计算 3 小结 相关文章 xff1a RTD 铂电阻测温原理与具体方法 RTD AD7793三线式铂电阻PT100 PT1000应用 RTD AD7793四线式铂电
  • 【RTD】AD7793四线式铂电阻PT100/PT1000应用

    文章目录 1 前言2 AD7793 四线式铂电阻测量2 1 阻值计算 3 小结 1 前言 上一篇文章描述的是RTD驱动芯片AD7793特点 xff0c 以及其与三线式RTD连接使用方法 本文描述四线式RTD与AD7793的使用 相关文章 x
  • 【RTD】AD7793两线式铂电阻PT100/PT1000应用

    文章目录 1 前言2 AD7793 两线式铂电阻测量2 1 阻值计算 3 小结 1 前言 上一篇文章描述的是RTD驱动芯片AD7793与四线式RTD连接使用方法 本文描述两线式RTD与AD7793的使用 相关文章 xff1a RTD 铂电阻
  • 【RTD】AD7793驱动程序

    文章目录 1 前言2 AD7793驱动程序2 1 spi访问接口2 2 寄存器和常用配置值2 3 初始化2 4 原始数据获取2 5 阻值换算 3 使用4 完整工程代码 1 前言 前面文章主要描述AD7793分别与两线 三线 四线RTD连接电
  • 【RTD】二分法查找和分段线性插值算法在RTD中应用

    文章目录 1 前言2 二分法查找2 1 复杂度2 2 实现 3 分段线性插值4 RTD实例 1 前言 处理器通过RTD采集电路 xff08 芯片 xff09 精确获得当前RTD电阻值后 xff0c 再结合RTD与温度线性关系表 xff0c
  • 24系列EEPROM/FRAM通用驱动库移植到RT-Thread

    文章目录 1 前言2 接口实现2 1 i2c收发函数实现2 2 页写延时函数2 3 写保护函数2 4 设备注册 3 对接RT Thread设备驱动3 1 标准设备驱动接口3 2 注册到RT Thread3 3 导出到msh3 4 测试 4
  • 【RT-Thread】TCA9534 8位I/O扩展器驱动软件包

    文章目录 1 简介1 1 目录结构1 2 许可证 2 芯片介绍3 支持情况4 使用说明4 1 依赖4 2 获取软件包4 3 初始化4 4 访问设备4 5 msh finsh测试查看设备注册执行sample 5 代码仓库 1 简介 tca95
  • 【代码质量】RAII在C++编程中的必要性

    文章目录 1 前言2 什么是RAII3 为什么用RAII4 RAII应用5 小结 1 前言 C C 43 43 相比其他高级编程语言 xff0c 具有指针的概念 xff0c 指针即是内存地址 C C 43 43 可以通过指针来直接访问内存空
  • C++ RAII典型应用之lock_guard和unique_lock模板

    文章目录 1 前言2 lock guard3 lock guard使用4 unique lock5 相关文章 1 前言 常用的线程间同步 通信 xff08 IPC xff09 方式有锁 xff08 互斥锁 读写锁 自旋锁 xff09 屏障
  • 基于STM32的实时操作系统FreeRTOS移植教程(手动移植)

    前言 xff1a 此文为笔者FreeRTOS专栏 下的第一篇基础性教学文章 xff0c 其主要目的为 xff1a 帮助读者朋友快速搭建出属于自己的公版FreeRTOS系统 xff0c 实现后续在实时操作系统FreeRTOS上的开发与运用 操
  • 通过sysinfo获取Linux系统状态信息

    系统运行状态信息是我们关注的重点 xff0c 通过当前系统的输出信息 xff0c 如内存大小 进程数量 运行时间等 xff0c 以便分析CPU负载 软硬件资源占用情况 xff0c 确保系统高效和稳定 Linux系统中 xff0c 提供sys
  • Keil AC5/Keil AC6/IAR指定数据绝对存储地址

    文章目录 1 前言2 实现方法3 例子 1 前言 编译过程中 xff0c 指定数据绝对存储地址在实际项目中会经常使用到或者必须用到 xff0c 这样使得项目实现某些功能可以非常灵活 xff0c 常用的场景有 xff1a IAP升级时候 xf
  • 嵌入式开发常用到的在线工具

    文章目录 IP地址计算常用加解密 xff0c AES DSE Base64 MD5异或 xff08 BCC xff09 校验CRC计算十六进制格式化字符串Json格式化HTML运行器常用在线编译器 xff08 C C 43 43 C JAV

随机推荐

  • STM32H7xx 串口DMA发送&接收(LL库)

    文章目录 1 前言2 STM32H7实现2 1 关键步骤2 2 注意事项 3 代码仓库 1 前言 关于串口DMA收发实现 xff0c 不同CPU其套路都是类似的 xff0c 不同之处在于寄存器配置 依赖BSP库等差异 串口DMA收发详细实现
  • 正交编码器溢出处理

    文章目录 1 正交编码器1 1 参数特性1 2 应用范围 2 正交编码器使用2 1 溢出问题2 2 中断模式2 3 循环模式延伸 1 正交编码器 正交编码器一般指的是增量式光栅 xff08 磁栅 xff09 编码器 xff0c 通常有三路输
  • PX4多旋翼期望姿态矩阵生成算法

    1 PX4多旋翼期望姿态生成算法 1 1 求期望体轴X轴向量1 2 求期望体轴Y轴向量1 3 求期望姿态矩阵1 4 求期望姿态角 1 PX4多旋翼期望姿态生成算法 PX4多旋翼期望姿态生成采用旋转矩阵方法 xff0c 基本思路为根据外环解算
  • git安装

    Git介绍 分布式 xff1a Git版本控制系统是一个分布式的系统 xff0c 是用来保存工程源代码历史状态的命令行工具 保存点 xff1a Git的保存点可以追踪源码中的文件 并能得到某一个时间点上的整个工程项目的状态 xff1b 可以
  • linux更改ssh连接方式将publickey改为用户名密码登录

    1 vim etc ssh sshd config 2 PermitRootLogin no 改为 PermitRootLogin yes 3 service restart sshd
  • dsp2812 pmsm foc之速度环电流环

    61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 速度环PI 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • leetcode(c++)

    放假没事刷几道leetcode xff0c 一些常见典型题的答案和解析 平时python用的比较多 xff0c 但分析复杂度的时候用python编程不方便 xff0c 所以刷题的时候用了c 43 43 C 43 43 基础 C 43 43
  • 基于STM32的超声波雷达项目【可拟合构建平面地图】(代码开源)

    前言 xff1a 本文为手把手教学基于STM32的超声波雷达 项目 HC SR04雷达 本次项目采用的是STM32作为MCU xff0c 搭配常用的HC SR04超声波模块与舵机SG90实现模拟雷达检测 的效果 模拟了雷达图UI 可以拟合构
  • android sdk manager不显示更新,只显示已安装,解决办法

    启动 Android SDK Manager xff0c 打开主界面 xff0c 依次选择 Tools Options xff0c 弹出 Android SDK Manager Settings 窗口 xff1b 在 Android SDK
  • detectron2学习:KeyError: “No object named ‘XXXXX‘ found in ‘BACKBONE‘ registry!“

    问题来源 在使用FB的框架detectron2改写模型的时候碰到了KeyError 34 No object named 39 XXXXX 39 found in 39 BACKBONE 39 registry 34 的bug 分析 xff
  • linux内核网络协议栈--linux网络设备理解(十三)

    网络层次 linux网络设备驱动与字符设备和块设备有很大的不同 字符设备和块设备对应 dev下的一个设备文件 而网络设备不存在这样的设备文件 网络设备使用套接字socket访问 xff0c 虽然也使用read write系统调用 xff0c
  • makefile使用--命令(三)

    一 Make的概念 Make这个词 xff0c 英语的意思是 34 制作 34 Make命令直接用了这个意思 xff0c 就是要做出某个文件 比如 xff0c 要做出文件a txt xff0c 就可以执行下面的命令 span class t
  • 【笔记】ubuntu18.04 ros melodic turtlebot3 源码下,导航gmapping仿真

    编写本笔记原因 xff1a 源码编译没问题 xff0c 但是在运行roslaunch turtlebot3 slam turtlebot3 slam launch slam methods 61 cartgrapher时出现下面这个错误 x
  • 从kernel层面分析synchronized、volatile,进大厂必备硬核小伎俩(上)

    synchronized volatile对于java程序员来说再熟悉不过了 xff0c 但 是你知道这两个关键字底层是如何实现的吗 xff08 甚至在操作系层面是 通过什么指令来实现的 xff09 xff1f 以及与其相关的术语 xff1
  • linux内核原理剖析——内存寻址(一)

    最近总想分享点硬核的原创文章出来 xff0c 一是硬核技术是一个程序员真正应该修炼 的内功 xff1b 二是修炼硬核技能是通往架构师领域的必经之路 本系列文章将分享关 于linux内核设计原理相关的内容 xff0c 希望能打通我们的七经八脉
  • linux内核原理剖析——磁盘寻址、分区

    继上一篇 lt lt linux内核原理剖析 内存寻址 xff08 一 xff09 gt gt 之后 xff0c 发现大家 对底层技术关注度比较高之后 xff0c 今天继上一篇的内存寻址一文后 xff0c 补 充一篇关于更为底层的 磁盘寻址
  • Redis集群从搭建到设计,总有一些你不曾了解的东西

    Redis集群是Redis服务器高可用的设计模型 xff0c 也是我们线上应用最多的Redis部署架构 本文主要针对Redis集 群入门搭建 Redis集群节点及其底层数据结构 hash槽 重新分片 消息等核心操作及原理进行分享 本文是基于
  • java成神之路学习线路

    自己总结了下java后端学习线路 xff0c 也是我八年的工作学习积累 xff0c 供各位同学参考 线路图还不全 xff0c 之后我会逐渐补全 下面思维导图中的技术 xff0c 我争取在2020年的博文中都分享给大家 xff0c 形成一个系
  • 实时操作系统系统FreeRTOS的学习(1)——任务

    前言 xff1a 在本专栏 FreeRTOS 中已经为读者朋友详细介绍了FreeRTOS以及关于FreeRTOS于STM32下的手动移植 从今天开始将带领大家系统学习FreeRTOS xff0c 这款常见的轻量化小型 实时操作系统 当然 x
  • 万字博文,Spring系列之抽丝剥茧Spring源码(一)

    当5G来临 xff0c 当211高校已经开启人工智能课程 xff0c 当甲骨文大批量裁员 xff0c 大家的心是否像我一样为之一颤呢 xff1f 当科技不断发展 xff0c 技术迅速迭代 xff0c 程序员愈发年轻化的今天 xff0c 而作