【Spring源码】Bean采用什么数据结构进行存储

简介: 我们再来看看中间新加入的阅读线索4,不知大家忘记了没。我们可以对照图片1的代码组织结构,发现这些没存储在包里的功能类都是比较杂乱的,想必是Spring觉得目前这些功能类还构不成一个包的体系,可能后面规模更大会统一集成起来管理。

一、前瞻

经过上篇源码阅读博客的实践,发现按模块阅读也能获得不少收获,而且能更加系统地阅读源码。

今天的阅读方式还是按模块阅读的方式,以下是Spring各个模块的组成。

在这里插入图片描述

那今天就挑Beans这个模块来阅读,先思考下本次阅读的阅读线索

  1. Beans模块使用了什么设计模式
  2. Beans模块里的Bean采用什么数据结构进行存储
  3. Beans模块里的Bean被Spring IOC容器管理,那管理Bean的具体实例是谁

二、探索

Ok,先整体看下Beans模块的代码组织结构。

在这里插入图片描述

看了组织结构,很好奇为什么spring不多创建几个文件包来分类,这个先作为我们的阅读线索4,等下继续探索。

factory包很显眼在第一个,应该就是创建Bean的工厂,而且应该使用了不少设计模式,我们按这个为入口进行探索。

在这里插入图片描述

我们以BeanFactory接口的实现类ClassPathXmlApplicationContext,来看看factory这个工厂是如何运行的,顺便解决我们的阅读线索1、2。

以下是ClassPathXmlApplicationContext的类图。

在这里插入图片描述

从类图里的链条可以知道,BeanFactory接口通过一系列的链条,生成了最终的实例ClassPathXmlApplicationContext。

BeanFactory作用在于生产Bean对象,而子类实现ClassPathXmlApplicationContext通过Class Path这种方式来生产Bean对象。

也就是采用了工厂方法模式,使每一个不同的子类实现都封装成了一个对象。

到这我们解决了阅读线索1

Beans模块使用了什么设计模式

我们再看看阅读线索2:Beans模块里的Bean采用什么数据结构进行存储

public interface BeanFactory {
   
   

    /**
     * Return an instance, which may be shared or independent, of the specified bean.
     * <p>This method allows a Spring BeanFactory to be used as a replacement for the
     * Singleton or Prototype design pattern. Callers may retain references to
     * returned objects in the case of Singleton beans.
     * <p>Translates aliases back to the corresponding canonical bean name.
     * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
     * @param name the name of the bean to retrieve
     * @return an instance of the bean.
     * Note that the return value will never be {@code null} but possibly a stub for
     * {@code null} returned from a factory method, to be checked via {@code equals(null)}.
     * Consider using {@link #getBeanProvider(Class)} for resolving optional dependencies.
     * @throws NoSuchBeanDefinitionException if there is no bean with the specified name
     * @throws BeansException if the bean could not be obtained
     */
    Object getBean(String name) throws BeansException;
}

BeanFactory主要是提供获取Bean的功能,那存储Bean的应该就在类图里链条的中间。

在这里插入图片描述

我们在链条的中间AbstractApplicationContext找到了getBen方法的实现,既然可以get,那存储Bean的数据结构也应该在里面。

@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
   
   
    DefaultListableBeanFactory beanFactory = this.beanFactory;
    if (beanFactory == null) {
   
   
        throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                                        "call 'refresh' before accessing beans via the ApplicationContext");
    }
    return beanFactory;
}

最终定位到了这段代码,可以看到引用了DefaultListableBeanFactory类,我们打开这个类。

在这里插入图片描述

可以看到存储Bean的最终数据结构就是这些Map,还采用了ConcurrentHashMap来支持并发,而Map的Key BeanDefinition就是Bean本身

到这我们就解决了阅读线索2

Beans模块里的Bean采用什么数据结构进行存储

阅读线索3也显而易见,管理Bean的也就是存储Bean的这些对象,如上文的DefaultListableBeanFactory

Beans模块里的Bean被Spring IOC容器管理,那管理Bean的具体实例是谁

我们可以全局搜索下private final Map<String, BeanDefinition>,看看哪些对象在存储Bean对象。

在这里插入图片描述

可以看到有两个,其中一个便是便是我们上文所探索的DefaultListableBeanFactory

三、总结

我们再来看看中间新加入的阅读线索4,不知大家忘记了没。

我们可以对照图1的代码组织结构,发现这些没存储在包里的功能类都是比较杂乱的,想必是Spring觉得目前这些功能类还构不成一个包的体系,可能后面规模更大会统一集成起来管理。

未完待续。。。

好了,今天的分享就到这👀。大家能否感受到通过按模块这种方式来阅读源码的乐趣呢

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

相关文章
|
6天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
1天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
28 9
|
25天前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
58 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
3天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
24 4
|
4天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
23 3
|
15天前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
18天前
|
存储 安全 数据库
除了 HashMap,还有哪些数据结构可以实现键值对存储?
【10月更文挑战第11天】 除了`HashMap`,其他常见支持键值对存储的数据结构包括:`TreeMap`(基于红黑树,键有序)、`LinkedHashMap`(保留插入顺序)、`HashTable`(线程安全)、`B-Tree`和`B+Tree`(高效存储大量数据)、`SkipList`(通过跳跃指针提高查找效率)及`UnorderedMap`(类似`HashMap`)。选择合适的数据结构需根据排序、并发、存储和查找性能等需求。
|
20天前
|
Java C++ 索引
让星星⭐月亮告诉你,LinkedList和ArrayList底层数据结构及方法源码说明
`LinkedList` 和 `ArrayList` 是 Java 中两种常见的列表实现。`LinkedList` 基于双向链表,适合频繁的插入和删除操作,但按索引访问元素效率较低。`ArrayList` 基于动态数组,支持快速随机访问,但在中间位置插入或删除元素时性能较差。两者均实现了 `List` 接口,`LinkedList` 还额外实现了 `Deque` 接口,提供了更多队列操作。
20 3
|
22天前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
22天前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)