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

news/2024/10/22 16:48:12/

IOC 加载过程 从 new ClassPathXmlApplicationContext开始

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

ClassPathXmlApplicationContext类构造方法

java">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() 详解

java">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对象。

java">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实例化 属性注入 初始化

关键方法

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

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

待续…

IOC容器步骤详解

面试详解


http://www.ppmy.cn/news/1455043.html

相关文章

产品AB测试设计

因为vue2项目升级到vue3经历分享1,vue2项目升级到vue3经历分享2,前端系统升级,界面操作也发生改变,为了将影响降到最低,是不能轻易让所有用户使用新系统的。原系统使用好好的,如果新界面用户不喜欢&#xf…

【c1】数据类型,运算符/循环,数组/指针,结构体,main参数,static/extern,typedef

文章目录 1.数据类型:编译器(compiler)与解释器(interpreter),中文里的汉字和标点符号是两个字节,不能算一个字符(单引号)2.运算符/循环:sizeof/size_t3.数组…

Android system property运作流程源码分析

一.序 前文分析了build.prop这个系统属性文件的生成,每个属性都有一个名称和值,他们都是字符串格式。属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性&#x…

【企业动态】爱尔兰客户到访东胜物联,共拓能源管理等解决方案

近日,来自爱尔兰的房屋数据监测客户莅临东胜物联(杭州黄龙国际中心)进行参观考察,双方就未来的广泛合作进行了深入的沟通交流。 来访期间,东胜物联CEO支江峰先生热情接待了客户,并陪同他们参观了产品展厅&…

欢乐钓鱼大师脚本,游戏托管一键操作!

欢迎来到《钓鱼大师乐趣无穷》!这里是一片充满了乐趣和挑战的钓鱼天地。不论你是刚刚入门的小白,还是已经成为老手的大神,本攻略将为你揭示如何在游戏中获得成功,并针对稀有鱼类的钓鱼技巧进行详细介绍。 一、初探钓鱼的乐趣 在《…

数据结构 栈实现队列

题目描述: 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): 实现 MyQueue 类: void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除并返回元素i…

Costas-Barker序列模糊函数仿真

文章目录 前言一、Costas 序列二、Barker 码三、Costas-Barker 序列模糊函数仿真1、MATLAB 核心代码2、仿真结果①、Costas-Barker 模糊函数图②、Costas-Barker 距离模糊函数图③、Costas-Barker 速度模糊函数图 四、资源自取 前言 Costas 码是一种用于载波同步的频率调制序列…

深入探讨SOCKS5代理:安全、隐私与技术实现

在当今的数字化世界中,网络安全和隐私已成为热门话题。企业和个人都在寻求更安全的方式来保护其数据和通信。在众多解决方案中,SOCKS5代理因其独特的功能和强大的灵活性而脱颖而出。本文将深入探讨SOCKS5代理的工作原理,其与HTTP代理的区别&a…