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工厂的序列化Idthis.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容器步骤详解

面试详解

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis集群分片

什么是集群 集群是由多个复制集组成的,能提供在多个redis节点间共享数据的程序集 简而言之就是将原来的单master主机拆分为多个master主机,将整个数据集分配到各主机上 集群的作用 集群中可以存在多个master,而每个master可以挂载多个slave自带哨兵的故障转移机制,不需要再去…

Python解释器3.8.2版本安装详细教程

Python解释器提取链接链接: https://pan.baidu.com/s/1eDvwYmUJ4l7kIBXewtN4EA?pwd1111 提取码:1111 演示版本为3.6.8,链接安装包为3.8.2版,包中附加pytharm安装包。 1.双击提取好的python-exe安装文件,会…

外企接受大龄程序员吗?

本人知乎账号同公众号:老胡聊Java,欢迎留言并咨询 亲身体会外企经历所见所闻,外企能接受大龄程序员。 1 大概是10年的时候,进一家知名外企,和我一起进的一位manager,后来听下来,年龄35&#xf…

0508_IO3

练习1&#xff1a; 1&#xff1a;使用 dup2 实现错误日志功能 使用 write 和 read 实现文件的拷贝功能&#xff0c;注意&#xff0c;代码中所有函数后面&#xff0c;紧跟perror输出错误信息&#xff0c;要求这些错误信息重定向到错误日志 err.txt 中去 1 #include <stdio.h…

【matlab基础知识代码】(十二)逆矩阵与广义逆矩阵

>> Hhilb(4);H1inv(H),norm(H*H1-eye(4))H1 1.0e03 *0.0160 -0.1200 0.2400 -0.1400-0.1200 1.2000 -2.7000 1.68000.2400 -2.7000 6.4800 -4.2000-0.1400 1.6800 -4.2000 2.8000ans 2.8455e-13 矩阵维数较大&#xff0c;警告: 矩阵接近奇…

svg画扇形进度动画

有人问下面这种图好怎么画&#xff1f;svg 想了下&#xff0c;确实用svg可以&#xff0c;可以这么设计 外层是一个容器放置内容&#xff0c;并且设置overflow:hidden&#xff0c; 内层放一个半径大于容器宽高一半的svg&#xff0c;并定位居中&#xff0c;然后svg画扇形&#x…

线程的组成、执行特点、创建的两种方式

线程的组成&#xff1a; cpu时间片 运行内存&#xff1a;栈、堆 线程的逻辑代码 线程执行的特点&#xff1a; 抢占式执行&#xff0c;结果随机&#xff0c;效率高&#xff0c;可以防止单一线程长时间独占CPU 在单核cpu中&#xff0c;宏观上同时执行&#xff0c;微观上顺序…

C++青少年简明教程之一:基础知识

C青少年简明教程之一&#xff1a;基础知识 电脑程序设计&#xff08;Computer programming&#xff09;&#xff0c;或称程序设计&#xff08;programming&#xff09;&#xff0c;是给出解决特定问题程序的过程&#xff0c;程序设计往往以某种程序设计语言为工具&#xff0c;给…

【软件测试】用例篇 -- 详解

一、测试用例的基本要素 测试用例&#xff08;Test Case&#xff09;是为了实施测试而向被测试的系统提供的一组集合&#xff0c;这组集合包含&#xff1a;测试环境、操作步骤、测试数据、预期结果等要素。&#xff08;注意&#xff1a;不需要执行结果&#xff0c;因为执行结果…

IO 5.8日

1&#xff1a;使用 dup2 实现错误日志功能 使用 write 和 read 实现文件的拷贝功能&#xff0c;注意&#xff0c;代码中所有函数后面&#xff0c;紧跟perror输出错误信息&#xff0c;要求这些错误信息重定向到错误日志 err.txt 中去 2&#xff1a;判断一个文件是否拥有用户可写…

Android单行字符串末尾省略号加icon,图标可点击

如图 设置仅显示单行字符串&#xff0c;末尾用省略号&#xff0c;加跟一个icon&#xff0c;icon可点击 tvName.text "test"val drawable ResourcesCompat.getDrawable(resources, R.mipmap.icon_edit, null)tvName.setCompoundDrawablesWithIntrinsicBounds(null,…

【如此简单!数据库入门系列】之无序不代表混乱 -- 堆文件

文章目录 前言堆文件链表实现页目录实现总结系列文章 前言 还记得上次遗留的问题吗&#xff1f; 以什么组织方式将数据保存在磁盘中&#xff1f; 今天我们接着讨论这个问题。 首先想一个问题&#xff1a;有一天&#xff0c;你开着自己心爱的大型SUV去超市购物。在停车场入口看…

威客网上招标系统(五)

目录 5 详细设计 5.1 系统首页 5.1.1系统首页&#xff08;网站首页index.jsp&#xff09; 5.1.2 下沙派威客网首页界面说明 5.2 站内新闻信息 5.2.1站内新闻操作界面 5.2.2系统主操作界面说明 5.3威客在线操作界面 5.3.1 威客在线操作界面 5.3.2威客在线说明 5.4系统…

文件IO-使用dup2实现错误日志功能及判断文件权限,并终端输出

1&#xff1a;使用 dup2 实现错误日志功能 使用 write 和 read 实现文件的拷贝功能&#xff0c;注意&#xff0c;代码中所有函数后面&#xff0c;紧跟perror输出错误信息&#xff0c;要求这些错误信息重定向到错误日志 err.txt 中去 代码&#xff1a; #incl…

kubectl_入门_Pod控制器

Pod控制器 在k8s中&#xff0c;按照pod的创建方式可以将其分为两类 自主式pod&#xff1a;k8s直接创建出来的pod&#xff0c;这种pod删除后就没有了&#xff0c;也不会重建控制器创建的pod&#xff1a;通过控制器创建的pod&#xff0c;这种pod删除了之后还会自动重建 1. 什么…

一张贴纸50万,炒房炒币的怎么都来炒CSGO皮肤了

一张贴纸50万&#xff0c;为什么炒房炒币的都来炒CSGO饰品了&#xff1f; 一张贴纸50万&#xff0c;炒房炒币的怎么都来炒CSGO皮肤了&#xff1f; 经常有人问我&#xff0c;天天看你们买卖装备&#xff0c;买卖皮肤&#xff0c;说到底这都是虚拟产品&#xff0c;看得见摸不着的…

Java_从入门到JavaEE_11

一、抽象类及抽象方法 1.认识抽象类及抽象方法 应用场景&#xff1a;当一个方法必须在父类中出现&#xff0c;但是这个方法又不好实现&#xff0c;就把该方法变成抽象方法&#xff0c;交给非抽象的子类去实现 实例&#xff1a; //抽象类 public abstract class 类名{//抽象方…

element-ui table sortable排序 掉后端接口方式

实例: 官方解释:如果需要后端排序&#xff0c;需将sortable设置为custom&#xff0c;同时在 Table 上监听sort-change事件&#xff0c;在事件回调中可以获取当前排序的字段名和排序顺序&#xff0c;从而向接口请求排序后的表格数据。 1.table上要加 sort-change"sortCha…

鸿蒙OpenHarmony开发板:【子系统配置规则】

子系统 子系统配置规则 通过build仓下的subsystem_config.json可以查看所有子系统的配置规则。 {"arkui": {"path": "foundation/arkui", # 路径"name": "arkui" # 子系统名},"ai": {&q…

【Keil程序大小】Keil编译结果Code-RO-RW-ZI分析

【Keil程序大小】Keil编译结果Code-RO-RW-ZI分析 下图为keil编译后的结果&#xff1a; 单位为Byte。Code是程序大小。RO是常量大小。RW是读写变量占用大小&#xff0c;如已初始化的静态变量和全局变量。ZI是全零变量占用大小&#xff0c;如未初始化的static修饰的静态变量、全局…