• Spring源码概述


    前言

    Spring是spring生态圈的基石,大家工作中常用的SSM框架,SpringBoot框架都是在Spring基础上衍生的,所以想更好的了解它们深入学习Spring是必不可少的。本章以综述的方式带大家快速了解Spring核心流程。


    一:Spring源码核心结构

    1.1 图示

    在这里插入图片描述

    1.2 Spring框架基本使用方式

    XML配置文件
    在这里插入图片描述
    使用函数
    在这里插入图片描述

    由上述Spring的使用过程可以衍生出两个问题:
    1. XML配置文件加载解析到容器中并实例化成Bean对象的主要步骤是什么?
    2. IOC容器是以什么数据结构存储Bean对象的?
    接下来我们就来探讨以上这两个问题。


    二:配置文件的信息如何加载并解析成IOC容器

    2.1 大致流程

    在这里插入图片描述

    2.2 Bean定义信息的定义方式

    相信大家通过观察上图很容易就发现出问题,难道Bean的定义信息只能通过XML配置文件来定义吗?显然不是。Spring为了提高拓展性提供了一个Bean定义信息的接口,只要想承载Bean定义信息的只需要实现这个规范即可。

    如图所示:
    在这里插入图片描述

    2.3 BeanDefinition对象

    BeanDefinition对象就是BeanDefinitionReader在解析Bean定义信息时,将Bean的定义信息封装成的对象。例如将xml文件中的bean标签的内容封装成对象,从这个对象中我们可以获取所有bean标签中定义的信息,也可以修改配置文件中定义的信息。

    看源码BeanDefinition的方法:
    在这里插入图片描述

    2.4 BeanDefinitionReader接口

    这个接口是所有想要承载Bean定义信息所需要实现的接口,该接口定义了一系列的规范。

    看BeanDefinitionReader的子实现类
    在这里插入图片描述

    2.5 从BeanDefinition对象实例化Bean对象

    相信很多小伙伴们觉得有了BeanDefinition对象就可以直接实例化Bean对象,这种思想咋一看好像是对的,毕竟都有了Bean的定义信息直接按照Bean定义信息封装的对象BeanDefinition来实例化对象不就可以了吗?但是如果在程序运行过程中要动态改变Bean的信息怎么办?要随时改变Bean的信息怎么办?例如<property name=url value=${jdbc.url},在这个情况下是绝对不能直接将BeanDefinition实例化成Bean对象的,因为IOC容器并不认识 ${jdbc.url},所以我们要在对象真正实例化进入容器之前进行拦截,替换掉 ${jdbc.url}。

    我们可以在Bean对象真正被实例化出来之前,加BeanFactoryPostProcessor,来达到动态修改Bean对象信息的目的。

    2.6 自定义BeanFactoryPostProcessor的演示

    在这里插入图片描述
    输出结果图:
    在这里插入图片描述

    2.7 PlaceholderConfigurerSupport占位符配置支持

    现在我们解决2.5提出的问题 ${jdbc_url}是怎么样被替换的呢?

    源码截图:
    在这里插入图片描述
    在这里插入图片描述

    2.8 对象实例化的方式

    对象实例化的方式一般有两种,一种是直接new,一种是通过反射,那么spring在实例化bean对象的时候采用那种方式呢?

    spring是通过反射来实例化bean对象的

    1. new对象的方式只能通过默认构造方法或者用户自定义的构造方法来为对象属性初始化,而通过反射的方式
    可以操作一个对象的所有属性,所有方法,所有注解,功能显得更加强大灵活,因此spring是通过反射来实
    化bean对象的。
    
    • 1
    • 2
    • 3

    2.9 对象创建的流程

    2.9.1 图示

    在这里插入图片描述

    2.9.2 填充属性

    填充属性阶段会执行配置文件中property标签的内容,通过setter方法给对象的属性赋值。

    注意:填充属性阶段是通过setter方法给属性赋值的,对象对应的属性必须有setter方法,否则property标签会失效。

    2.9.3 执行int-method初始化方法

    可以在类的成员方法中写一个初始化方法,在xml配置文件中的bean标签中指定该方法为init-method,那么在对象初始化的执行初始化方法阶段就会执行该方法。

    示例

    实体类
    在这里插入图片描述
    测试类
    在这里插入图片描述
    结果:
    在这里插入图片描述

    2.10 bean对象初始化阶段的细节分析

    2.10.1 流程图

    在这里插入图片描述

    2.10.2 Aware接口

    Aware接口是一个标记接口,顾名思义这个接口是感知的意思,即bean对象能够感知到所在的spring 容器对象。只要一个对象实现了Aware接口,并重写了setter方法,当这个对象交由spring容器创建的时候,spring容器会将自身的对象作为参数传入,这样我们就可以通过该bean对象的实例获取容器对象。

    示例
    实体类
    在这里插入图片描述
    测试类
    在这里插入图片描述
    结果
    在这里插入图片描述
    spring容器的Aware接口有很多,大家可以通过源码查看。


    三:spring容器的存储结构

    spring容器是以Map集合来存储bean对象的。
    那么Map集合的key和value的类型有多少种呢?

    3.1 string-object型

    key为bean对象的id值,value为bean对象
    相当于是以by-Name方式从容器中取出对象

    3.2 class-object类型

    key为bean对象的类信息,value为bean对象
    相当于是以by-Type方式从容器中取出对象

    3.3 string-objectFactory

    key为bean对象的id值,value为生产bean对象的工厂

    3.4 string-BeanDefinition

    key为bean对象的id值,value为bean对象的定义信息。


    四:总流程图

    在这里插入图片描述

  • 相关阅读:
    常用的排序算法
    redis,mongoDB,mysql,Elasticsearch区别
    一点一点学习C++之笔记001
    华硕 A550C 安装 CentOS7 后无法连接 wifi 问题排查解决
    SPDK LVOL +Blobstore +FIO 使用
    torch VS tensorflow 同功能的api
    Haddop集群的简单搭建
    V831——车牌识别
    亚马逊气候友好型承诺所有认证
    pgsql在navicate导出sql再去其他库导入时会遇到的小问题
  • 原文地址:https://blog.csdn.net/ai15013602354/article/details/125439290