Spring refresh()源码解析

Spring refresh()源码解析

什么是Spring refresh()方法?

refresh()是Spring中负责刷新ApplicationContext的方法,它会重新读取配置文件、重新实例化和初始化Bean对象,同时注入新创建的对象。它是在Spring启动时被调用的方法。

refresh()方法的过程是怎样的?

refresh()方法的整个过程大致分为以下几个步骤:

1. prepareRefresh()方法

该方法主要是为了準备 ApplicationContext 的信息,包括:
* 关闭 ApplicationContext 的状态设置为 False
* 初始化资源加载器
* 记录 ApplicationContext 的启动时间

2. obtainFreshBeanFactory()方法

该方法会刷新 BeanFactory,形成应用中定义的所有 bean 的定义和关系列表,包括:
* 使用 AbstractRefreshableApplicationContext 的 refreshBeanFactory() 方法加载 BeanFactory
* 使用 ConfigurableBeanFactory 的 setSerializationId() 方法设置序列化 ID
* 注册环境相关的 BeanDefinition

3. prepareBeanFactory()方法

该方法主要是为了将 Spring 配置文件中的信息加载到 BeanFactory 中,包括:
* 设置 BeanFactory 的 ClassLoader
* 添加 ApplicationContextAwareProcessor 的 BeanPostProcessor
* 添加 BeanFactoryAwareProcessor 的 BeanPostProcessor
* 添加与“当前环境”相关的 BeanPostProcessor
* 设置忽略的自动装配接口
* 注册默认的 bean
* 注册 BeanFactory 自定义的编辑器
* 注册 Spring 带有的 JAVA API 编辑器
* 设置表达式语言

4. postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法

该方法主要是对 BeanFactory 进行后处理,包括:
* 注册 BeanPostProcessors
* 执行 Scopes 的注册
* 注册 Scope 回调
* 引入相关的依赖注入 BeanPostProcessor
* 初始化 MessageSources 组件

5. invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法

该方法主要是执行 BeanFactoryPostProcessor ,包括:
* 按优先级排序执行 BeanDefinitionRegistryPostProcessor
* 按优先级排序执行 BeanFactoryPostProcessor
* 调用 ApplicationListenerDetector

6. registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)方法

该方法主要是为 BeanFactory 注册 BeanPostProcessor,包括:
* 添加了 BeanPostProcessorChecker,确保 BeanPostProcessor 的总数匹配 BeanFactory 中的 Bean 的总数
* 使用 InstantiationAwareBeanPostProcessor 接口处理程序
* 使用 SmartInstantiationAwareBeanPostProcessor 接口处理程序

7. initMessageSource()方法

该方法主要是初始化信息源 MessageSource

8. initApplicationEventMulticaster()方法

该方法主要是初始化 ApplicationEventMulticaster 用来监听 ApplicationContext 发布的事件

9. onRefresh()方法

该方法主要提供子类覆盖,以便在 ApplicationContext 已成功刷新并激活所有 bean 之后执行特定的处理

10. registerListeners()方法

该方法主要是向 ApplicationEventMulticaster 注册特定的监听器

11. finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)方法

该方法主要是完成 BeanFactory 的初始化,包括:
* 调用所有未调用的 BeanFactoryPostProcessor,执行 AfterInitialization
* 让所有 BeanPostProcessor 检查匹配 Bean 中的 Bean
* 调用 postProcessorsBeforeInitialization() 和 postProcessorsAfterInitialization()
* 调用所有实现了 InitializingBean 的 Bean 的 afterPropertiesSet() 方法
* 调用自定义的 init 方法

12. finishRefresh()方法

该方法主要是为了清除 Spring 的所有剩余缓存

示例说明

示例1

我们现在假设有一个ApplicationContext,它包含了一个foo bean,当执行refresh()方法时,Spring 将刷新所有 bean,并将 foo bean 重新加载到容器中。

ApplicationContext ctx = ... // create ApplicationContext
// 此时foo bean已被加载到ctx中
ctx.getBean("foo");
ctx.refresh();
// 调用refresh()方法之后,foo bean被重新加载到ctx中
ctx.getBean("foo");

示例2

在这个示例中,我们将会在refresh()方法中使用 setServletContext() 方法设置 ServletContext 接口,以便在 ApplicationContext 中进行注册。

ApplicationContext ctx = ... // create ApplicationContext
ServletContext servletContext = ... // create ServletContext
ctx.setServletContext(servletContext);
ctx.refresh();

在这一示例中,如果在refresh()方法之前没有设置 ServletContext 接口,则会出现异常。这是因为某些 bean 是通过 ServletContext 实例进行注入的,而 ServletContext 在此时尚未可用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring refresh()源码解析 - Python技术站

(0)
上一篇 2023年6月20日
下一篇 2023年6月20日

相关文章

  • Python实现数字小写转大写的示例详解

    Python实现数字小写转大写的示例详解 在Python中,我们可以使用以下步骤将数字小写转换为大写: 创建一个字典,将数字与对应的大写形式进行映射。例如: num_dict = { ‘0’: ‘零’, ‘1’: ‘壹’, ‘2’: ‘贰’, ‘3’: ‘叁’, ‘4’: ‘肆’, ‘5’: ‘伍’, ‘6’: ‘陆’, ‘7’: ‘柒’, ‘8’: ‘捌’…

    other 2023年8月18日
    00
  • spring中AOP 注解开发示例详解

    针对“spring中AOP 注解开发示例详解”的完整攻略,我将分为以下几个部分进行讲解: 1. AOP 概述 AOP,即 Aspect Oriented Programming,面向切面编程,是一种程序设计的思想,可以让程序逻辑分散到各个部分,从而增加代码的可维护性和辅助性。Spring框架提供了完善的AOP实现,可以通过纯Java编写切面代码,实现统一的业…

    other 2023年6月27日
    00
  • JavaScript的原型是什么你知道吗

    JavaScript的原型是什么你知道吗 JavaScript中的原型是一种特殊的对象,它用于实现对象之间的继承关系。每个JavaScript对象都有一个原型,它定义了对象的属性和方法。当我们访问一个对象的属性或方法时,如果对象本身没有定义该属性或方法,JavaScript会自动查找并使用原型中的对应属性或方法。 原型链 JavaScript中的原型通过原型…

    other 2023年10月15日
    00
  • window.onload 加载完毕的问题及解决方案(上)

    针对“window.onload 加载完毕的问题及解决方案(上)”这个话题,我们需要分别从以下几个方面进行讲解: 什么是 window.onload? window.onload 是 JavaScript 中一个非常重要的事件,用于在页面中所有的资源(如文件、图片等)都加载完成后触发,也就是在文档的所有内容(包括 DOM、CSS、JS、图片)都已经加载完成后…

    other 2023年6月25日
    00
  • 如何修改select标签的默认下拉箭头样式?

    在 HTML 中,<select> 标签用于创建下拉列表。默认情况下,下拉列表的样式是由浏览器决定的,包括下拉箭头的样式。但是,我们可以使用 CSS 来修改下拉箭头的样式。下面是一个完整攻略,包含两个示例说明。 方法一:使用 ::after 伪元素 我们可以使用 CSS 中的 ::after 伪元素来修改下拉箭头的样式。具体步骤如下: 将 &lt…

    other 2023年5月8日
    00
  • Mapstruct对象插入数据库某个字段总是为空的bug详解

    下面是关于“Mapstruct对象插入数据库某个字段总是为空的bug”问题的完整攻略,包含了两条示例说明。 问题描述 在使用Mapstruct进行对象映射,将对象插入数据库后,发现其中一个字段总是为空,其他字段正常插入,而且在对象中该字段也有值,这是为什么呢? 解决过程 在解决该问题的过程中,需要对Mapstruct进行深入了解,并从以下方面进行排查: 映射…

    other 2023年6月25日
    00
  • jQuery实现自定义事件的方法

    要实现自定义事件,我们需要使用jQuery中的trigger()方法和bind()方法。下面是具体的步骤和示例说明: 1. 使用bind()方法绑定自定义事件 首先,我们需要使用bind()方法来绑定自定义事件。bind()方法可以将自定义事件绑定到一个DOM元素上,当这个DOM元素被触发时,该自定义事件就会被触发。 下面是一个示例,我们将一个自定义事件“m…

    other 2023年6月25日
    00
  • python链表类中获取元素实例方法

    获取元素是链表类中常见的操作之一。对于Python链表,要获取元素通常有两种方法:索引和迭代器。 索引 要获取链表中的某个元素,可以通过索引来实现。在Python链表中,可以使用下标操作符[]来获取链表中特定位置的元素。下标从0开始,代表链表的第1个元素。 示例1:获取链表中指定位置的元素 class Node: def __init__(self, dat…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部