当前位置: 首页 > news >正文

Spring核心方法:Refresh全解(WebMVC如何装配、关联)

Spring核心方法:Refresh全解(WebMVC如何装配、关联)

这里是一个表格,列出了Spring容器刷新过程中执行的方法以及它们的作用:

方法名称描述
prepareRefresh()初始化一些属性和状态,例如启动时间戳、活动标志、环境变量等。
obtainFreshBeanFactory()创建一个新的Bean Factory,并配置一些基本属性。
prepareBeanFactory()对Bean Factory进行进一步的配置。
postProcessBeanFactory()允许子类对Bean Factory进行后处理。
invokeBeanFactoryPostProcessors()调用所有在Spring容器中注册的BeanFactoryPostProcessor。
registerBeanPostProcessors()注册所有在Spring容器中注册的Bean后处理器。
initMessageSource()初始化Spring容器中的消息源。
initApplicationEventMulticaster()初始化Spring容器中的事件多路广播器。
onRefresh()允许子类在Spring容器初始化完成后进行一些自定义的初始化操作。
registerListeners()注册所有在Spring容器中注册的监听器。
finishBeanFactoryInitialization()初始化所有在Spring容器中注册的单例Bean。
finishRefresh()发布一个刷新完成事件,表示Spring容器已经成功初始化并准备就绪。

需要注意的是,这些方法的具体实现取决于具体的ApplicationContext实现类,例如XmlWebApplicationContext、AnnotationConfigApplicationContext等。因此,在具体使用时需要结合具体的实现类来学习和理解这些方法。

Spring容器刷新过程详解

Spring容器在初始化过程中会执行一系列的操作,以确保容器中的各种组件都正确地创建和配置。这个过程被称为容器刷新,它由AbstractApplicationContext类的refresh()方法触发。以下是Spring容器刷新过程中执行的方法以及它们的作用:

好的,现在让我来整理一下您之前提到的四个问题,并结合源码对refresh()方法以及牵扯到的其他方法进行详细的中文解释。

  1. Spring容器刷新方法概述

    Spring容器刷新是指在Spring容器初始化时,创建和配置Bean Factory,并初始化Spring容器中的各种组件的过程。refresh()方法是AbstractApplicationContext类中用于刷新Spring容器的主要方法。该方法在容器初始化时被调用,用于创建和配置Bean Factory,并初始化Spring容器中的各种组件。

  2. refresh()方法源码解释

    以下是refresh()方法的源码,逐行解释如下:

    @Override
    public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 1. 准备刷新prepareRefresh();// 2. 获取新的Bean FactoryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 3. 准备Bean FactoryprepareBeanFactory(beanFactory);try {// 4. 允许子类对Bean Factory进行后处理postProcessBeanFactory(beanFactory);// 5. 调用BeanFactoryPostProcessorinvokeBeanFactoryPostProcessors(beanFactory);// 6. 注册Bean后处理器registerBeanPostProcessors(beanFactory);// 7. 初始化MessageSourceinitMessageSource();// 8. 初始化事件多路广播器initApplicationEventMulticaster();// 9. 其他特殊Bean的初始化工作onRefresh();// 10. 注册监听器registerListeners();// 11. 初始化所有剩余的单例BeanfinishBeanFactoryInitialization(beanFactory);// 12. 发布刷新完成事件finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// 销毁已创建的BeandestroyBeans();// 重置活动标志cancelRefresh(ex);// 抛出异常throw ex;}finally {// 重置公共缓存resetCommonCaches();}}
    }
    

以上是refresh()方法的源码,接下来我们逐步解释每一步的具体作用。

  1. prepareRefresh()方法源码解释

prepareRefresh()方法是refresh()方法的第一步,主要用于初始化一些属性和状态,例如启动时间戳、活动标志、环境变量等。以下是prepareRefresh()方法的源码,逐行解释如下:

protected void prepareRefresh() {// 1. 切换到活动状态this.startupDate = System.currentTimeMillis();this.closed.set(false);this.active.set(true);if (logger.isDebugEnabled()) {logger.debug("Refreshing " + this);}// 2. 初始化属性源initPropertySources();// 3. 验证所有必需的属性是否可解析getEnvironment().validateRequiredProperties();// 4. 存储预刷新的ApplicationListenersif (this.earlyApplicationListeners != null) {this.applicationListeners.addAll(this.earlyApplicationListeners);this.earlyApplicationListeners = null;}// 5. 允许收集早期的ApplicationEvents,等待多路广播器可用时发布...this.earlyApplicationEvents = new LinkedHashSet<>(this.applicationEvents);this.applicationEvents = null;// 6. 创建并配置新的ApplicationEventMulticasterthis.eventMulticaster = new SimpleApplicationEventMulticaster(this);// 7. 添加某些系统监听器this.eventMulticaster.setTaskExecutor(this.taskExecutor);this.eventMulticaster.addApplicationListener(new ApplicationListener<ContextClosedEvent>() {@Overridepublic void onApplicationEvent(ContextClosedEvent event) {closeEventMulticaster();}});this.eventMulticaster.addApplicationListener(new ApplicationListener<ContextRefreshedEvent>() {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {initApplicationEventListeners();}});this.eventMulticaster.addApplicationListener(new ApplicationListener<RequestHandledEvent>() {@Overridepublic void onApplicationEvent(RequestHandledEvent event) {if (event.getException() != null && shouldPublishEvent(event.getException())) {publishEvent(new ContextPublishingEvent(AbstractApplicationContext.this, event));}}});// 8. 发布早期的ApplicationEvents,现在我们终于有了多路广播器...Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;for (ApplicationEvent earlyEvent : earlyEventsToProcess) {this.eventMulticaster.multicastEvent(earlyEvent);}// 9. 发布ContextRefreshedEvent,即使上下文尚未完全刷新,也需要发布此事件,因为初始化器通常会使用此事件执行某些任务。this.eventMulticaster.multicastEvent(new ContextRefreshedEvent(this));// 10. 初始化生命周期处理器initLifecycleProcessor();// 11. 首先将刷新传播到生命周期处理器getLifecycleProcessor().onRefresh();// 12. 发布最终事件finishRefresh();
}

以上是prepareRefresh()方法的源码,接下来我们逐步解释每一步的具体作用。

  1. SpringMVC通过refresh()方法关联Spring容器

在SpringMVC中,DispatcherServlet是整个Web应用的前端控制器,它负责接收所有的请求并将请求分发到相应的处理器中。在DispatcherServlet初始化时,会创建一个Spring容器,并通过refresh()方法进行初始化。以下是DispatcherServlet中关于refresh()方法的部分源码:

protected WebApplicationContext initWebApplicationContext() {WebApplicationContext wac = null;try {// 1. 创建WebApplicationContextwac = createWebApplicationContext(getWebApplicationContextClass());}catch (Throwable ex) {// 创建失败,抛出异常throw new ServletException("Context initialization failed", ex);}if (wac == null) {// 创建失败,抛出异常throw new ServletException("Context is null");}// 2. 配置WebApplicationContextconfigureAndRefreshWebApplicationContext(wac);return wac;
}protected void configureAndRefreshWebApplicationContext(WebApplicationContext wac) {// 1. 配置WebApplicationContextwac.setServletContext(getServletContext());wac.setServletConfig(getServletConfig());wac.setNamespace("dispatcher-servlet");wac.addApplicationListener(new ContextLoaderListener(wac));// 2. 刷新WebApplicationContextwac.refresh();
}

可以看到,在DispatcherServlet中,首先通过createWebApplicationContext()方法创建一个WebApplicationContext对象,然后通过configureAndRefreshWebApplicationContext()方法对其进行配置和刷新。在configureAndRefreshWebApplicationContext()方法中,首先对WebApplicationContext进行配置,例如设置ServletContext、ServletConfig等属性,然后调用refresh()方法对其进行初始化。这样,SpringMVC就通过DispatcherServlet将Spring容器关联到了Web应用中。

  1. 结论

本文主要介绍了Spring容器刷新的概述、refresh()方法的源码解释、prepareRefresh()方法的源码解释、以及SpringMVC通过refresh()方法关联Spring容器的具体过程。通过对这些方法的详细解释,希望能够帮助大家更好地理解Spring容器的刷新过程以及SpringMVC中的应用。

详细解释

接下来,我们将详细解释Spring容器刷新过程中执行的每个方法,以帮助您更好地理解Spring容器的工作原理。

prepareRefresh()

prepareRefresh()方法是Spring容器刷新过程中的第一个方法。在这个方法中,Spring容器会执行以下操作:

  • 设置容器的启动时间、活动标志和环境变量等属性。

  • 初始化容器的属性源,包括系统属性、环境变量和配置文件等。

  • 创建一个新的ApplicationEventMulticaster,用于广播容器中的事件。

  • 注册一些默认的监听器,例如ContextRefreshedEvent、ContextClosedEvent等。

需要注意的是,prepareRefresh()方法是一个模板方法,它的具体实现取决于具体的ApplicationContext实现类。例如,在XmlWebApplicationContext中,prepareRefresh()方法会加载Web应用程序的XML配置文件。

obtainFreshBeanFactory()

obtainFreshBeanFactory()方法用于创建一个新的BeanFactory,并配置一些基本属性。在这个方法中,Spring容器会执行以下操作:

  • 创建一个新的DefaultListableBeanFactory,它是Spring容器中BeanFactory的默认实现。

  • 设置BeanFactory的ClassLoader、PropertyEditor注册器等基本属性。

  • 注册一些默认的Bean,例如ApplicationContext、ApplicationEventMulticaster等。

需要注意的是,obtainFreshBeanFactory()方法也是一个模板方法,它的具体实现取决于具体的ApplicationContext实现类。例如,在XmlWebApplicationContext中,obtainFreshBeanFactory()方法会加载Web应用程序的XML配置文件。

相关文章:

Spring核心方法:Refresh全解(WebMVC如何装配、关联)

Spring核心方法&#xff1a;Refresh全解(WebMVC如何装配、关联) 这里是一个表格&#xff0c;列出了Spring容器刷新过程中执行的方法以及它们的作用&#xff1a; 方法名称描述prepareRefresh()初始化一些属性和状态&#xff0c;例如启动时间戳、活动标志、环境变量等。obtainF…...

TCP:三次握手四次挥手及相关问题:

连接—三次握手&#xff1a; 流程图&#xff1a; 过程详解&#xff1a; 客户端(connect)连接服务器&#xff08;listen) Client将标志位SYN置为1,随机产生一个值seqx, 并将该数据包发送给Server, Client进入SYN_ SENT状态&#xff0c;等待Server确认。Server收到数据包后由标…...

链式二叉树--前序中序后序遍历,高度,节点个数问题

目录 前言&#xff1a; 一&#xff1a;链式二叉树的结构定义 二&#xff1a;链式二叉树的遍历--->前序&#xff0c;中序&#xff0c;后序 1.前序 递归展开图分析 2.中序 递归展开图分析 3.后序 三&#xff1a;二叉树结点的求解 1.二叉树总结点 递归展开分析 2…...

HCIA——TCP协议详解

目录 1、TCP概念及协议头部格式 1.1TCP特点 1.2TCP协议协议头部格式 1.3字段进行介绍 1.3.1源端口和目的端口 1.3.2序号(seq) 1.3.3确认序号(ack) 1.3.4数据偏移 1.3.5标志位 1.3.6窗口 1.3.7校验和 1.3.8紧急指针 2、TCP的可靠性 2.1 TCP可靠性的保障 2.2排序机…...

Hadoop大数据应用:Linux 部署 HDFS 分布式集群

目录 一、实验 1.环境 2.Linux 部署 HDFS 分布式集群 3.Linux 使用 HDFS 文件系统 二、问题 1.ssh-copy-id 报错 2. 如何禁用ssh key 检测 3.HDFS有哪些配置文件 4.hadoop查看版本报错 5.启动集群报错 6.hadoop 的启动和停止命令 7.上传文件报错 8.HDFS 使用命令 一…...

纯 CSS 实现文字换行环绕效果

实现效果 实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</title><…...

【爬虫逆向】Python逆向采集猫眼电影票房数据

进行数据抓包&#xff0c;因为这个网站有数据加密 !pip install jsonpathCollecting jsonpathDownloading jsonpath-0.82.2.tar.gz (10 kB)Preparing metadata (setup.py) ... done Building wheels for collected packages: jsonpathBuilding wheel for jsonpath (setup.py) .…...

解析服务器下载速度:上行、下行与带宽之谜

在日常使用中&#xff0c;我们经常会遇到从服务器下载内容速度忽快忽慢的情况&#xff0c;即便服务器的硬件配置如4核CPU、8GB内存和12Mbps的带宽看似足够。为何会出现这种现象&#xff1f;这背后涉及到网络中的上行、下行以及带宽等关键概念。本文旨在揭开这些术语背后的含义&…...

计算机网络的概念

目录 <计算机网络的定义> <计算机网络的形成与发展> 1.第一阶段远程联机阶段----60年代以前: 2.第二阶段多机互联网络阶段----60年代中期: 3.第三阶段标准化网络阶段----70年代末: 4.第四阶段网络互联与高速网络阶段一90年代: <计算机网络的未来--下一代…...

MATLAB中的脚本和函数有什么区别?

MATLAB中的脚本和函数是两种不同的代码组织方式&#xff0c;它们在结构、功能和使用方式上有显著的区别。以下是对这两种方式的详细解释&#xff0c;总计约2000字。 一、MATLAB脚本 MATLAB脚本是一种包含多条MATLAB命令的文件&#xff0c;这些命令按照在文件中的顺序依次执行…...

从电影《沙丘》说起——对人工智能的思考

正文 从《沙丘》开始说起 之前看《沙丘》电影&#xff0c;里面有一类角色叫门泰特&#xff0c;这类人大脑可以飞快地运算&#xff0c;在电影设定里是替换人工智能、机器运算的存在。男主保罗也是这类型的人&#xff0c;但他可能基因更强大&#xff0c;吸食了香料后&#xff0…...

使用Python进行自然语言处理(NLP):NLTK与Spacy的比较【第133篇—NLTK与Spacy】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 使用Python进行自然语言处理&#xff08;NLP&#xff09;&#xff1a;NLTK与Spacy的比较 自…...

学习笔记--在线强化学习与离线强化学习的异同(3)

这篇博文很多部分仅代表个人学习观点&#xff0c;欢迎大家与我一起讨论 强化学习与离线强化学习的区别 强化学习和离线强化学习都是机器学习的分支&#xff0c;主要用于训练智能体以在不断尝试和错误的过程中学习如何最大化累积奖励。它们之间的主要区别在于数据的获取方式和训…...

使用Thymeleaf导出PDF,页眉插入图片与内容重叠?

CSS 打印分页功能 需求&#xff1a;打印 在第一页的内容被挤到第二页的时候&#xff0c;又想每一页页头都有相同的样式&#xff0c;使用页眉。 问题&#xff1a;第二页的内容与页眉重叠了&#xff1f; 查各路找出的原因&#xff1a;header 页眉不占空间 解决&#xff1a;不…...

python网络编程:通过socket实现TCP客户端和服务端

目录 写在开头 socket服务端&#xff08;基础&#xff09; socket客户端&#xff08;基础&#xff09; 服务端实现&#xff08;可连接多个客户端&#xff09; 客户端实现 数据收发效果 写在开头 近期可能会用python实现一些网络安全工具&#xff0c;涉及到许多关于网络…...

论文阅读——RSGPT

RSGPT: A Remote Sensing Vision Language Model and Benchmark 贡献&#xff1a;构建了一个高质量的遥感图像描述数据集&#xff08;RSICap&#xff09;和一个名为RSIEval的基准评估数据集&#xff0c;并在新创建的RSICap数据集上开发了基于微调InstructBLIP的遥感生成预训练…...

长连接技术

个人学习记录&#xff0c;欢迎指正 1.轮询 1.1 轮询的形式 短连接轮询 前端每隔一段时间向服务端发起一次Http请求来获取数据。 const shortPolling () > { const intervalHandler setInterval(() > {fetch(/xxx/yyy).then(response > response.json()).then(respo…...

供电系统分类详解

一、供电系统分类 电力供电系统一般有5种供电模式&#xff0c;常用的有&#xff1a;IT系统&#xff0c;TT系统&#xff0c;TN系统&#xff0c;其中TN系统又可以分为TN-C&#xff0c;TN-S&#xff0c;TN-C-S。 1、TN-C系统&#xff08;三相四线制&#xff09; 优点: 该系统中…...

基于centos7的k8s最新版v1.29.2安装教程

k8s概述 Kubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态&#xff0c;其服务、支持和工具的使用范围相当广泛。 Kubernetes 这个名字源于希腊语&…...

【赠书第20期】AI绘画与修图实战:Photoshop+Firefly从入门到精通

文章目录 前言 1 入门篇&#xff1a;初识Photoshop与Firefly 2 进阶篇&#xff1a;掌握Photoshop与Firefly的核心技巧 3 实战篇&#xff1a;运用Photoshop与Firefly进行创作 4 精通篇&#xff1a;提升创作水平&#xff0c;拓展应用领域 5 结语 6 推荐图书 7 粉丝福利 前…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…...

macOS 终端智能代理检测

&#x1f9e0; 终端智能代理检测&#xff1a;自动判断是否需要设置代理访问 GitHub 在开发中&#xff0c;使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新&#xff0c;例如&#xff1a; fatal: unable to access https://github.com/ohmyzsh/oh…...

用js实现常见排序算法

以下是几种常见排序算法的 JS实现&#xff0c;包括选择排序、冒泡排序、插入排序、快速排序和归并排序&#xff0c;以及每种算法的特点和复杂度分析 1. 选择排序&#xff08;Selection Sort&#xff09; 核心思想&#xff1a;每次从未排序部分选择最小元素&#xff0c;与未排…...

无需布线的革命:电力载波技术赋能楼宇自控系统-亚川科技

无需布线的革命&#xff1a;电力载波技术赋能楼宇自控系统 在楼宇自动化领域&#xff0c;传统控制系统依赖复杂的专用通信线路&#xff0c;不仅施工成本高昂&#xff0c;后期维护和扩展也极为不便。电力载波技术&#xff08;PLC&#xff09;的突破性应用&#xff0c;彻底改变了…...