面试之Spring的启动原理

2023-05-16

引入

为什么突然说一下Spring启动原理呢,因为之前面试的时候,回答的那可谓是坑坑洼洼,前前后后,补补贴贴。。。

总而言之就是不行,再次看一下源码发掘一下。。。

在Spring Boot还没有广泛到家家在用的时候,我们都还在书写繁琐的配置,什么web.xml、spring.xml、bean.xml等等。虽然现在很少,可以说几乎没有企业在去使用Spring的老一套,而会去使用Spring Boot约定大于配置来进行快速开发,但是,Spring的也要去学习,去挖掘,毕竟是我们Java程序员的基础呀。

spring的启动是建筑在servlet容器之上的,所有web工程的初始位置就是web.xml,它配置了servlet的上下文(context)和监听器(Listener)

web.xml

<!--上下文监听器,用于监听servlet的启动过程-->
    <listener>
        <description>ServletContextListener</description>
        <!--这里是自定义监听器,个性化定制项目启动提示-->
        <listener-class>com.trace.app.framework.listeners.ApplicationListener</listener-class>
    </listener>
    <!--dispatcherServlet的配置,这个servlet主要用于前端控制,这是springMVC的基础-->
    <servlet>
        <servlet-name>service_dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/services/service_dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--spring资源上下文定义,在指定地址找到spring的xml配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/application_context.xml</param-value>
    </context-param>
    <!--spring的上下文监听器-->
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <!--Session监听器,Session作为公共资源存在上下文资源当中,这里也是自定义监听器-->
    <listener>
        <listener-class>
            com.trace.app.framework.listeners.MySessionListener
        </listener-class>
    </listener>

Spring启动过程

spring的上下文监听器

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/application_context.xml</param-value>
</context-param>

<listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
 </listener>

spring的启动其实就是IOC容器的启动过程,通过上述的第一段配置 <context-param> 是初始化上下文,然后通过后一段的的<listener>来加载配置文件,其中调用的spring包中的ContextLoaderListener这个上下文监听器,ContextLoaderListener是一个实现了ServletContextListener接口的监听器,他的父类是 ContextLoader,在启动项目时会触发contextInitialized上下文初始化方法。

public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
}

调用了父类ContextLoader的initWebApplicationContext(event.getServletContext());方法,很显然,这是对ApplicationContext的初始化方法,也就是到这里正是进入了springIOC的初始化。

接下来看一下initWebApplicationContext(event.getServletContext())的工作:

if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
            throw new IllegalStateException(
                    "Cannot initialize context because there is already a root application context present - " +
                    "check whether you have multiple ContextLoader* definitions in your web.xml!");
        }

        Log logger = LogFactory.getLog(ContextLoader.class);
        servletContext.log("Initializing Spring root WebApplicationContext");
        if (logger.isInfoEnabled()) {
            logger.info("Root WebApplicationContext: initialization started");
        }
        long startTime = System.currentTimeMillis();

        try {
            // Store context in local instance variable, to guarantee that
            // it is available on ServletContext shutdown.
            if (this.context == null) {
                this.context = createWebApplicationContext(servletContext);
            }
            if (this.context instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
                if (!cwac.isActive()) {
                    // The context has not yet been refreshed -> provide services such as
                    // setting the parent context, setting the application context id, etc
                    if (cwac.getParent() == null) {
                        // The context instance was injected without an explicit parent ->
                        // determine parent for root web application context, if any.
                        ApplicationContext parent = loadParentContext(servletContext);
                        cwac.setParent(parent);
                    }
                    configureAndRefreshWebApplicationContext(cwac, servletContext);
                }
            }
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

            ClassLoader ccl = Thread.currentThread().getContextClassLoader();
            if (ccl == ContextLoader.class.getClassLoader()) {
                currentContext = this.context;
            }
            else if (ccl != null) {
                currentContextPerThread.put(ccl, this.context);
            }

            if (logger.isDebugEnabled()) {
                logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
                        WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
            }
            if (logger.isInfoEnabled()) {
                long elapsedTime = System.currentTimeMillis() - startTime;
                logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
            }

            return this.context;
        }
        catch (RuntimeException ex) {
            logger.error("Context initialization failed", ex);
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
            throw ex;
        }
        catch (Error err) {
            logger.error("Context initialization failed", err);
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
            throw err;
        }

总结:

  • 创建WebApplicationContext。
  • 加载对应的spring配置文件中的Bean。
  • 将WebApplicationContext放入ServletContext(Java Web的全局变量)中。

接下来,来到了configureAndRefreshWebApplicationContext()方法

作用:

就是用来加载spring配置文件中的Bean实例的。这个方法于封装ApplicationContext数据并且初始化所有相关Bean对象。它会从web.xml中读取名为 contextConfigLocation的配置,这就是spring xml数据源设置,然后放到ApplicationContext中,最后调用传说中的refresh方法执行所有Java对象的创建。

总结:
在这里插入图片描述

总结

  1. 首先对于一个web应用,需要部署到web容器中,web容器提供了一个全局的上下文环境,ServletContext,SpringIOC的宿主环境。

  2. 其次,在web容器启动时,触发容器初始化,web.xml中提供的有ContextLoaderListener监听器会监听这个事件,初始化方法contextInitialized被调用,初始化spring上下文
    WebApplicationContext接口,实现类时XmlWebApplicationContext即SpringIOC容器,对应的Bean定义是有context-param标签定义指定,然后存储到ServletContext中,方便获取。

  3. ContextLoaderListener监听初始化完成后,开始初始化web.xml中配置的Servlet,指DisapatchServlet前端控制器,用来匹配,转发,处理每个Servlet请求,DisaptchServlet初始化时会创建自己的IOC上下文,用来持有Spring MVC的相关bean。
    首先会从之前初始化存储在ServletContext中的上下文左右parent上下文,再初始化自己的上下文,大概的工作就是初始化处理器映射、视图解析等。这个servlet自己持有的上下文默认实现类也是xmlWebApplicationContext。然后存储到ServletContext。每个Servlet拥有自己的上下文,也会共享parent的上下文。

下期讲解refresh()做了什么,以及Spring Boot的启动原理,敬请观看,谢谢。。。
下期讲解refresh()做了什么,以及Spring Boot的启动原理,敬请观看,谢谢。。。
下期讲解refresh()做了什么,以及Spring Boot的启动原理,敬请观看,谢谢。。。

在这里插入图片描述
JVM内存泄漏和内存溢出的原因
JVM常用监控工具解释以及使用
Redis 常见面试题(一)
ClickHouse之MaterializeMySQL引擎(十)
三种实现分布式锁的实现与区别
线程池的理解以及使用

号外!号外!

最近面试BAT,整理一份面试资料,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。想获取吗?如果你想提升自己,并且想和优秀的人一起进步,感兴趣的朋友,可以在扫码关注下方公众号。资料在公众号里静静的躺着呢。。。

  • 喜欢就收藏
  • 认同就点赞
  • 支持就关注
  • 疑问就评论

一键四连,你的offer也四连

————————————————

本文作者:Java技术债务
原文链接:https://www.cuizb.top/myblog/article/1643358761
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试之Spring的启动原理 的相关文章

  • ubuntu安装字体

    先安装 span class token function sudo span span class token function apt get span span class token function install span y
  • windows 压缩指定目录下每个目录和文件为zip文件的powershell脚本

    某个文件夹下有几十个子文件夹 xff0c 想要单个压缩每个子文件夹备份到云盘 如果手动操作会有点累 xff0c 尝试写个脚本吧 版本 适用于win10 win11 其他版本未测试 一 编写脚本 众所周知windows下有两种自带脚本cmd和
  • SpringMVC的配置和执行流程

    要想成功的配置和调试springmvc xff0c 了解掌握它的执行流程是必不可少的 xff0c 话不多说 xff0c 看下图 xff1a 我们边说执行边讲配置 xff0c 首先 xff0c 想要使用springmvc xff0c 依赖是必
  • Maven安装与配置详解、多镜像节点的配置

    下载 Maven是Apache下面的一个项目 xff0c 官网下载地址 xff1a https maven apache org download cgi 历史版本下载地址 xff1a https archive apache org di
  • 使用FTPClient上传文件到ftp服务器。并解决图片损坏问题。

    1 先借鉴此博客的方法 xff08 此博客的方法上传txt文件没有问题 xff0c 但是上传的图片文件会损坏 xff09 https blog csdn net weixin 37196194 article details 5500166
  • libnet的使用详解

    最近搬砖需要对libnet进行介绍在这里对知识进行汇总 1 libnet简介 在 libnet 出现以前 xff0c 如果要构造数据包并发送到网络中 xff0c 程序员要通过一些复杂的接口来处理 libnet 的出现 xff0c 为程序员提
  • electron启动报错

    一个简单的程序启动居然报错了 xff0c 那就排查原因吧 xff0c 搜索网上的资料没有一个一样的 xff0c 大致类似的说的是electron版本和node不一致 还有说是electron的版本问题 但排查后都不是 xff0c 最后我把m
  • 手把手使用 Egg+TypeScript+mongoDB快速实现增删改查

    创建一个Egg的TS项目 xff08 Egg js官方教程 xff09 安装MogoDB Egg 依赖 span class token function npm span span class token function install
  • 小白学java——做一个歌手比赛系统(一)

    xfeff xfeff 完整代码加实验报告都在https download csdn net download qq 39980334 11232331 我已经设置成0积分下载了 xff0c 有需要的自行下载 xff0c 有问题的多看看代码
  • 使用尾插法创建链表并打印输出

    include lt stdio h gt include lt stdlib h gt include lt string h gt typedef struct LNode struct LNode next int data LNod
  • RabbitMQ 发展史与安装

    RabbitMQ 天降奇兵 解决的实例1 xff1a 统计用户的行为 xff0c 利用消息队列解耦模块和认证服务器 xff0c 认证模块被设计为 xff0c 在每一次请求页面的时候 xff0c 发送一条认证请求消息到rabbitmq xff
  • 小白学java------做一个歌手比赛系统(二)

    完整代码加实验报告都在 https download csdn net download qq 39980334 11232331 我已经设置成0积分下载了 xff0c 有需要的自行下载 xff0c 如果页面打不开可能还在审核中 xff08
  • 网络爬虫入门

    1 网络爬虫 网络爬虫 xff08 Web crawler xff09 xff0c 是一种按照一定的规则 xff0c 自动地抓取万维网信息的程序或者脚本 1 1 爬虫入门程序 1 1 1 环境准备 JDK1 8IntelliJ IDEAID
  • Java API入门篇

    文章目录 1 API1 1 API概述1 2 如何使用API帮助文档 2 String类2 1 String类概述2 2 String类的特点2 3 String类的构造方法2 4 创建字符串对象两种方式的区别2 5 字符串的比较2 5 1
  • Java异常篇

    文章目录 1 异常2 JVM默认处理异常的方式3 try catch方式处理异常4 Throwable成员方法5 编译时异常和运行时异常的区别6 throws方式处理异常7 throws和throw的区别8 自定义异常 1 异常 异常的概述
  • Java集合篇

    文章目录 1 Collection集合1 1 集合体系结构1 2 Collection集合概述和基本使用1 3 Collection集合的常用方法1 4 Collection集合的遍历1 5 集合使用步骤图解1 6 集合的案例 Collec
  • macOS下安装JDK11和配置环境变量

    1 下载 官网下载地址 华为云下载JDK11地址 tar包或者dmg xff0c 二者区别在于 xff1a tar你自己解压 xff0c 放在你想要的地方 xff08 配置JAVA HOME的时候是你自己选的位置 xff01 xff09 d
  • Java文件操作、IO流

    文章目录 1 File类1 1 File类概述和构造方法1 2 File类创建功能1 3 File类判断和获取功能1 4 File类删除功能 2 递归2 1 递归2 2 递归求阶乘2 3 递归遍历目录 3 IO流3 1 IO流概述和分类3
  • Java多线程

    文章目录 1 实现多线程1 1 进程和线程1 2 实现多线程方式一 xff1a 继承Thread类1 3 设置和获取线程名称1 4 线程优先级1 5 线程控制1 6 线程的生命周期1 7 实现多线程方式二 xff1a 实现Runnable接
  • Java编程思想(第4版)习题答案

    https span class token operator span span class token operator span span class token operator span greggordon span class

随机推荐

  • Bootstrap给表格设置宽度不起作用

    更改名称为table的class 将table layout属性设置为fixed span class token selector table span span class token punctuation span span cla
  • C++作用域运算符“::“的作用

    1 当存在具有相同名称的局部变量时 xff0c 要访问全局变量 include lt iostream gt using namespace std int x Global x int main int x 61 10 Local x c
  • HTML实现鼠标拖动元素排序

    1 简介 拖放 xff08 Drag和 drop xff09 是 HTML5 标准的组成部分 xff0c 为了使元素可拖动 xff0c 必须把 draggable 属性设置为 true xff0c 整个拖拽事件触发的顺序如下 xff1a d
  • MacOS安装svn客户端

    一 安装Homebrew环境 打开终端 输入以下命令 bin zsh c span class token string 34 span class token variable span class token variable span
  • MySql数据库root账户无法远程登陆解决办法

    最近换了新的腾讯云服务器后 xff0c 通过宝塔面板安装了mysql 数据库 xff0c 之后使用root用户通过navicat远程连接登录不了 解决办法如下 两行代码ok MySQL5 7和MySql8 开启root 用户远程访问 mys
  • MacOS修改Hosts文件

    1 苹果Mac电脑上 xff0c hosts文件的路径为 etc hosts xff0c 打开VI编辑 span class token function sudo span span class token function vim sp
  • ERD Online 4.0.0 免费私有部署方案

    文章目录 1 快速安装2 前置条件 3 一键安装 4 兼容性列表4 1 云主机兼容性列表4 2 虚拟机兼容性列表 1 快速安装 ERD Online的服务理念 xff1a 能喂到嘴里 xff0c 绝不递到手里 2 前置条件 一台至少配置为
  • mysql: error while loading shared libraries: libtinfo.so.5 解决办法

    Centos8中安装mysql8 xff0c 服务启动后 xff0c 连接服务时报错为以下错误信息 mysql error span class token keyword while span loading shared librari
  • trilead-ssh2连接不上centos服务器Caused by: java.io.IOException: Cannot negotiate, proposals do not match.

    导致此问题的原因是ssh升级后 xff0c 为了安全 xff0c 默认不在采用原来一些加密算法 xff0c 我们手工添加进去即可 1 步骤一 修改ssh的配置文件 etc ssh sshd config 搜索KexAlgorithms xf
  • macos安装nvm

    文章目录 1 概述2 安装注意事项3 安装nvm 1 概述 nvm 即 node version manager xff0c 好处是方便切换 node js 版本 2 安装注意事项 卸载从node官网下载pkg安装的nodesudo rm
  • Linux下生产者消费者问题的C语言实现

    注 xff1a 查看全文请关注作者 xff0c 或点击前往 xff1a 生产者 消费者问题的C语言实现 实验六 生产者 消费者问题实现 实验题目 要求 在Linux操作系统下用C实现经典同步问题 xff1a 生产者 消费者 xff0c 具体
  • ftpClient文件上传成功但总是返回false

    ftpClient storeFile newFileName is xff1b 文件上传成功但总是返回false flag span class token operator 61 span ftpClient span class to
  • “佛祖保佑“代码注释

    注释如下 oo0oo o8888888o 88 34 34 88 0 61 0 96 39 39 39
  • android带视频和图片的轮播(banner)解决方案

    方案只包含一个视频和多张图片 xff0c 如果又多个视频的 xff0c 可以修改适配器中的的播放器为一个list xff0c 并且在滑动中做相应的释放操作 一 xff1a 实现一个视频和多张图片的轮播banner 使用到第三方框架有 1 轮
  • Android灯光系统(硬件访问服务框架)

    Android灯光系统 硬件访问服务框架 Java类 xff1a LightsService java LightsService java通过调用 xff0c LightsService JNI来实现com android server包
  • Ubuntu16.04简易安装pycharm社区版

    1 首先到官网下载linux版本的pycharm xff0c 为了使用方便 xff0c 直接安装社区版 https www jetbrains com pycharm download section 61 linux xff08 因为虚拟
  • vue 严格格式问题

    用vue cli脚手架搭建开发环境 xff0c 会自动安装eslint严格格式 xff0c 如果代码格式不按照严格模式写 xff0c 会经常报警告 xff08 如缩进4个空格会警告 xff09 xff0c 如下图是一些警告类型 xff1a
  • vue watch深度监控一个对象下新增属性不生效问题

    先简单还原下项目中遇到的问题 xff1a adc为一个空对象 xff0c watch深度监听abc下的pageNum属性 xff08 此时还没有 xff09 data return abc watch 39 abc 39 deep true
  • python 归并排序

    归并排序 xff08 Merge Sort xff09 是一种典型的递归法排序 它把复杂的 排序过程分解成一个简单的合并子序列的过程 至于怎么得到这个子 序列 xff0c 就得自己调用自己了 归并排序首先要做的就是将数列分成左右两部分 xf
  • 面试之Spring的启动原理

    引入 为什么突然说一下Spring启动原理呢 xff0c 因为之前面试的时候 xff0c 回答的那可谓是坑坑洼洼 xff0c 前前后后 xff0c 补补贴贴 总而言之就是不行 xff0c 再次看一下源码发掘一下 在Spring Boot还没