spring ioc 容器加载过程 refresh() 方法详解

IOC 加载过程 从 new ClassPathXmlApplicationContext开始

ApplicationContext context = new 
ClassPathXmlApplicationContext("classpath:application.xml");

ClassPathXmlApplicationContext类构造方法

public ClassPathXmlApplicationContext(String[] configLocations,
 boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
    super(parent);
    this.setConfigLocations(configLocations);
    if (refresh) {
    	// 执行刷新操作
        this.refresh();
    }
}

核心类和接口

ApplicationContext接口 其实就是一个BeanFactory

作用: 加载配置文件中定义的 bean,并进行管理。

继承了ListableBeanFactory,这个ListableBeanFactory接口可以获取多个bean。
继承了HierarchicalBeanFactory接口,这个接口可以在应用这起多个BeanFactory,然后将多个BeanFactory设置父子关系。
getAutowireCapableBeanFactory() : 用来自动装配Bean

BeanDefinitionReader

配置文件解析器,如将配置文件中的 bean 信息解析成对应的 BeanDefinition 对象。

xml 文件解析使用是就是BeanDefinitionReader 实现类 XmlBeanDefinitionReader。

BeanFactoryPostProcessor

可以修改 Spring 上下文中 BeanDefinition 信息。

BeanFactory

是所有 Bean 容器的根接口,定义了 spring 容器基本方法。如使用 getBean(beanName,Class) 获取对象。

refresh() 详解

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //1:准备刷新上下文环境。
        prepareRefresh();

        //2:刷新并获取刷新后的 BeanFactory,将配置文件解析为BeanDefinition对象。
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        //3:对 Bean 工厂进行填充属性。
        prepareBeanFactory(beanFactory);

        try {
            //4:beanFactory的后置处理器,空方法,具体由子类实现。
            // 使用设计模式中的模板方法,是一个钩子函数。
            postProcessBeanFactory(beanFactory);

            //5:实例化并调用所有注册的beanFactory后置处理器。
            invokeBeanFactoryPostProcessors(beanFactory);

            //6:加载 BeanPostProcessors。
            registerBeanPostProcessors(beanFactory);

            //7:国际化处理,为上下文实例化并注册一个MessageSource。
            initMessageSource();

            //8:初始化并注册一个事件广播器用来发布事件。
            initApplicationEventMulticaster();

            //9:空方法,由子类实现,使用设计模式中的模板方法,是一个钩子函数。
            onRefresh();

            //10:注册监听器,在所有注册的bean中查找Listener bean,注册到消息广播器中,即向监听器发布事件。
            registerListeners();

            //11:初始化所有的非懒加载的单实例bean(bean的生命周期实例化 属性注入 初始化 完成)
            finishBeanFactoryInitialization(beanFactory);

            //12:最后刷新容器 发布刷新事件。
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

图解

在这里插入图片描述

prepareRefresh()

准备刷新上下文环境。

obtainFreshBeanFactory()(重要)

刷新并获取刷新后的 BeanFactory,将配置文件解析为BeanDefinition对象。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //刷新bean工厂()
    refreshBeanFactory();
    //返回之前容器准备工作的时候创建的的bean工厂也就是DefaultListableBeanFactory(很重要)
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}
protected final void refreshBeanFactory() throws IllegalStateException {
    //由于BeanFactory只能刷新一次,多线程情况下可能导致线程安全问题,所有使用cas原子操作来保证
    if (!this.refreshed.compareAndSet(false, true)) {
        throw new IllegalStateException(
                "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
    }
    //指定Bean工厂的序列化Id
    this.beanFactory.setSerializationId(getId());
}
prepareBeanFactory()

对 Bean 工厂进行填充属性。

postProcessBeanFactory()

beanFactory的后置处理器,空方法,具体由子类实现。使用设计模式中的模板方法,是一个钩子函数。

invokeBeanFactoryPostProcessors()

实例化并调用所有注册的beanFactory后置处理器。

registerBeanPostProcessors()

加载 BeanPostProcessors。

initMessageSource()

国际化处理,为上下文实例化并注册一个MessageSource。

initApplicationEventMulticaster()

初始化并注册一个事件广播器用来发布事件。

onRefresh()

空方法,由子类实现,使用设计模式中的模板方法,是一个钩子函数。

registerListeners()

注册监听器,在所有注册的bean中查找Listener bean,注册到消息广播器中,即向监听器发布事件。

finishBeanFactoryInitialization()(重要)

初始化所有的非懒加载的单实例bean(bean的生命周期实例化 属性注入 初始化 完成)。

bean实例化 属性注入 初始化

关键方法

AbstractAutowireCapableBeanFactory类的doCreateBean方法
// 其中
createBeanInstance(beanName, mbd, args); // 实例化
populateBean(beanName, mbd, instanceWrapper); // 属性注入
initializeBean(beanName, exposedObject, mbd)  // 初始化
finishRefresh()

最后刷新容器发布刷新事件。

待续…

IOC容器步骤详解

面试详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/596301.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

知识图谱在提升大语言模型性能中的应用:减少幻觉与增强推理的综述

幻觉现象指的是模型在生成文本时可能会产生一些听起来合理但实际上并不准确或相关的输出,这主要是由于模型在训练数据中存在知识盲区所致。 为了解决这一问题,研究人员采取了多种策略,其中包括利用知识图谱作为外部信息源。知识图谱通过将信息…

电子取证平航杯的复现

闻早起部分: 一、闻早起的windows10电脑 (1).“闻早起”所使用的笔记本电脑使用何种加密程式? 1.在EFI文件中找到加密程式 (2) 教徒“闻早起”所使用的笔记本电脑中安装了一款还原软件,其版本…

测试人员必用的10个Chrome扩展插件

背景:谷歌Chrome浏览器是全球所有测试人员最受欢迎和必备的浏览器之一,Chrome浏览器为我们提供了许多扩展的选择,可以让我们高效和省时地完成工作。以下为作者观点: 1. Testsigma Recorder Testsigma Recorder用于记录与网络应用…

嵌入式Linux学习第二天

今天学习linuxC编程。首先要熟悉linux下编写c程序的过程。 编写程序Hello World! 首先创建存放程序的文件夹,如下图所示: 接下来在创建一个文件夹来保存这节要编写的代码。指令:mkdir 3.1 接下来我们要设置VIM编辑器的一些配置&#xff0…

【简单介绍下Debian常用命令】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

AI部署指南

部署指南 建议大家尽可能的自己去部署,如果实在懒得搞,可以找我来帮你部署,详情参考 服务器代部署说明。 由于时间仓促,文档可能尚未详尽,我将在后续逐步补充详细的说明文档。 架构草图 项目依赖 必选依赖 MySQ…

DS二叉搜索树

前言 我们在数据结构初阶专栏已经对二叉树进行了介绍并用C语言做了实现,但是当时没有对二叉搜树进行介绍,而是把他放到数据结构进阶构专栏的第一期来介绍,原因是后面的map和set(红黑树)是基于搜索树的,这里…

Java-(乘法表之后)增强for循环

这里我们先做个了解,之后我会在数组中进行详细介绍Java5引入了一种主要用于数组或集合的增强型for循环Java增强型for循环语法格式如下 For(声明语句:表达式){ //代码语句 } 声明语句:声明新的局部变量,该变量的类型…

Windows中安装的PostgreSQL 数据库如何重启

1. 使用Windows服务管理器 打开“运行”对话框(按WinR键)。输入services.msc并按回车,这将打开服务列表。在服务列表中找到PostgreSQL服务。它通常命名为“PostgreSQL”后面跟着版本号和实例名称,例如“PostgreSQL 13 - mydb”。…

【云原生】Pod 的生命周期(一)

【云原生】Pod 的生命周期(一)【云原生】Pod 的生命周期(二) Pod 的生命周期(一) 1.Pod 生命期2.Pod 阶段3.容器状态3.1 Waiting (等待)3.2 Running(运行中)3…

后缀表达式

什么是后缀表达式? 在计算机科学和数学领域,表达式求值是一项基本且频繁的任务。我们熟知的中缀表达式(如 7 15 ∗ 1 4 ∗ 1)直观易读,但在计算机处理时却需要复杂的栈或递归算法来解析。相比之下,后缀表…

深度学习中的优化算法:选择现有的还是自创?

深度学习中的优化算法 深度学习中的优化算法:选择现有的还是自创?现有优化算法的优势**优点包括**: 开发新的优化算法的考虑**开发新算法的原因**:**开发新算法的风险**: 实用建议结论 深度学习中的优化算法&#xff1…

RabbitMQ 是如何做延迟消息的 ?——Java全栈知识(15)

RabbitMQ 是如何做延迟消息的 ? 1、什么是死信? 当一个队列中的消息满足下列情况之一时,可以成为死信(dead letter): 消费者使用 basic.reject 或 basic.nack 声明消费失败,并且消息的 reque…

5-在Linux上部署各类软件

1. MySQL 数据库安装部署 1.1 MySQL 5.7 版本在 CentOS 系统安装 注意:安装操作需要 root 权限 MySQL 的安装我们可以通过前面学习的 yum 命令进行。 1.1.1 安装 配置 yum 仓库 # 更新密钥 rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022# 安装Mysql…

rk3588局域网推流

最近无意间看见在网上有使用MediaMtx插件配合ffmpeg在Windows来进行推流,然后在使用其他软件进行拉流显示数据图像的,既然windows都可以使用 ,我想linux应该也可以,正好手上也有一块RK3588的开发板,就测试了一下&#…

iOS ------ JSONModel源码

一,JSONModel的基本使用 1,基本使用方法 - (instancetype)initWithDictionary:(NSDictionary *)dict error:(NSError **)err; - (instancetype)initWithData:(NSData *)data error:(NSError **)error; - (instancetype)initWithString:(NSString *)str…

Linux网络-部署YUM仓库及NFS共享服务

目录 一.YUM仓库服务 1.YUM概述 1.1.YUM(Yellow dog Updater Modified) 2.准备安装源 2.1.软件仓库的提供方式 2.2.RPM软件包的来源 2.3.构建CentOS 7 软件仓库 2.4.在软件仓库中加入非官方RPM包组 3.一键安装软件包的工具: 好处&a…

申请Sectigo证书流程详解

Sectigo(前身为Comodo CA),是目前主流SSL证书的一种,目前全球范围内应用度也非常广泛,是目前众多品牌中市场份额最大的一个品牌了,在全球证书市场份额占比约为40%。 其超高的市场份额占比主要还是基于其超…

021、Python+fastapi,第一个Python项目走向第21步:ubuntu 24.04 docker 安装mysql8集群、redis集群(二)

系列文章目录 pythonvue3fastapiai 学习_浪淘沙jkp的博客-CSDN博客https://blog.csdn.net/jiangkp/category_12623996.html 前言 安装redis 我会以三种方式安装,在5月4号修改完成 第一、直接最简单安装,适用于测试环境玩玩 第二、conf配置安装 第三…

【Leetcode 42】 接雨水

基础思路: (1)需要将问题最小化,首先计算第i个位置最多容纳多少雨水(细长的一条水柱),然后求和就是总的雨水量; (2)第i个位置容纳雨水量 min(左侧最高, 右…