深入理解 Spring Boot 启动原理

本文将从以下几个方面进行详细阐述:

  1. Spring Boot 启动过程概述
  2. BeanFactory 初始化
  3. Bean 的实例化和依赖注入
  4. Aware 接口的设置
  5. Bean 的初始化
  6. 单例 Bean 的后处理
  7. Spring 启动后的后处理
  8. 启动 HTTP 流量入口

一、Spring Boot 启动过程概述

Spring Boot 的启动过程可以分为几个主要阶段,从启动类开始,经过一系列的初始化和配置过程,最终启动 HTTP 服务器并准备好处理请求。

1.1 启动类

每一个 Spring Boot 应用程序都有一个主类,这个类包含了 main 方法,通常使用 @SpringBootApplication 注解标记。@SpringBootApplication 是一个组合注解,包含了 @Configuration, @EnableAutoConfiguration, 和 @ComponentScan

@SpringBootApplication
public class MySpringBootApplication {public static void main(String[] args) {SpringApplication.run(MySpringBootApplication.class, args);}
}

SpringApplication.run 方法启动了整个 Spring Boot 应用程序,触发了一系列的自动配置和初始化过程。

1.2 SpringApplication 初始化

SpringApplication 类负责引导和启动 Spring 应用程序。它的 run 方法完成了以下几件事情:

  • 创建并配置 ApplicationContext
  • 准备环境变量。
  • 加载所有的 ApplicationListener
  • 启动并刷新 ApplicationContext
  • 执行所有的 ApplicationRunnerCommandLineRunner
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return new SpringApplication(primarySource).run(args);
}

1.3 应用上下文的创建和刷新

ApplicationContext 是 Spring 框架中的核心容器。Spring Boot 使用不同的 ApplicationContext 实现来处理不同类型的应用程序(如 AnnotationConfigServletWebServerApplicationContext 用于 Web 应用程序)。上下文的刷新包含了所有 Bean 的创建和初始化过程,这也是我们将深入探讨的部分。

二、BeanFactory 初始化

在 Spring 中,BeanFactory 是最基本的容器接口,负责管理 Bean 的创建、配置和生命周期。Spring Boot 在启动过程中,会首先初始化 BeanFactory,并通过 BeanFactoryPostProcessor 对其进行配置和处理。

2.1 BeanFactoryPostProcessor

BeanFactoryPostProcessor 是在 BeanFactory 标准初始化之后执行的,用于对 BeanFactory 进行定制和修改。典型的 BeanFactoryPostProcessor 包括 PropertyPlaceholderConfigurerCustomEditorConfigurer

public interface BeanFactoryPostProcessor {void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

BeanFactoryPostProcessor 在所有 Bean 被实例化之前执行,这使得它们可以用来修改 Bean 定义或添加一些自定义的初始化逻辑。

三、Bean 的实例化和依赖注入

BeanFactory 初始化完成后,Spring 开始实例化各个 Bean 并进行依赖注入。这一过程涉及到以下几个重要步骤:

3.1 Bean 实例化

Spring 通过反射机制来实例化 Bean。对于每个定义的 Bean,Spring 都会调用其默认构造函数或指定的构造函数来创建 Bean 实例。

TestSpringOrder order = new TestSpringOrder();

3.2 依赖注入

依赖注入是 Spring 核心功能之一,通过 @Autowired 注解可以自动注入依赖的 Bean。Spring 使用 AutowiredAnnotationBeanPostProcessor 处理这些注解,并注入相应的依赖。

@Autowired
private SomeService someService;

AutowiredAnnotationBeanPostProcessor 会在 Bean 实例化后对其进行扫描,找到所有的 @Autowired 字段,并注入相应的依赖。

四、Aware 接口的设置

Spring 提供了一系列的 Aware 接口,用于让 Bean 获得 Spring 容器的一些资源。实现这些接口的 Bean 在初始化时会被注入相应的资源。

4.1 常见的 Aware 接口

  • BeanNameAware: 提供 Bean 的名称。
  • BeanFactoryAware: 提供 BeanFactory 实例。
  • ApplicationContextAware: 提供 ApplicationContext 实例。
  • EnvironmentAware: 提供 Environment 实例。
  • ResourceLoaderAware: 提供 ResourceLoader 实例。
public class MyBean implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}
}

4.2 Aware 设置过程

Spring 在初始化 Bean 时,会检查 Bean 是否实现了任何 Aware 接口,如果是,则调用相应的设置方法注入资源。例如,对于 ApplicationContextAware,Spring 会调用其 setApplicationContext 方法,将 ApplicationContext 注入到该 Bean 中。

五、Bean 的初始化

在完成实例化和依赖注入后,Spring 开始初始化 Bean,这一过程包括执行初始化方法和初始化回调。

5.1 BeanPostProcessor

BeanPostProcessor 是一个扩展点,允许在 Bean 初始化前后进行一些自定义处理。Spring 在 Bean 初始化之前和之后分别调用 postProcessBeforeInitializationpostProcessAfterInitialization 方法。

public interface BeanPostProcessor {Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

5.2 @PostConstruct 和 InitializingBean

Spring 提供了两种方式来定义 Bean 的初始化方法:

  • 使用 @PostConstruct 注解标记初始化方法。
  • 实现 InitializingBean 接口并重写 afterPropertiesSet 方法。
@PostConstruct
public void init() {// initialization logic
}@Override
public void afterPropertiesSet() throws Exception {// initialization logic
}

5.3 自定义初始化方法

除了 @PostConstructInitializingBean 之外,Spring 还允许在 Bean 定义中指定自定义的初始化方法。

@Bean(initMethod = "customInit")
public MyBean myBean() {return new MyBean();
}

六、单例 Bean 的后处理

在所有单例 Bean 初始化完成后,Spring 进行一些额外的处理,包括触发事件和执行一些特殊的回调。

6.1 SmartInitializingSingleton

SmartInitializingSingleton 是 Spring 3.1 引入的一个接口,用于在所有单例 Bean 初始化完成后执行一些逻辑。

public interface SmartInitializingSingleton {void afterSingletonsInstantiated();
}

6.2 事件监听

Spring 提供了丰富的事件机制,允许在应用程序不同阶段发布和监听事件。单例 Bean 初始化完成后,Spring 会发布 ContextRefreshedEvent

@Component
public class MyListener implements ApplicationListener<ContextRefreshedEvent> {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {// handle event}
}

七、Spring 启动后的后处理

在应用程序上下文刷新完成后,Spring 还会进行一些额外的处理,如启动定时任务和发布其他应用事件。

7.1 SmartLifecycle

SmartLifecycle 是一个更高级的生命周期接口,允许在应用程序上下文刷新完成后执行一些操作,如启动后台任务。

public interface SmartLifecycle extends Lifecycle, Phased {boolean isAutoStartup();void stop(Runnable callback);
}

7.2 定时任务

Spring 通过 @Scheduled 注解支持定时任务。在应用程序上下文刷新完成后,所有标记了 @Scheduled 的方法都会按指定的计划执行。

@Scheduled(fixedRate = 5000)
public void scheduledTask() {// task logic
}

7.3 发布事件

Spring 在启动过程中会发布一系列事件,允许开发人员在特定的时机执行一些自定义逻辑。例如,在上下文刷新完成后,Spring 会发布 ContextRefreshedEvent

八、启动 HTTP 流量入口

Spring Boot 默认集成了嵌入式的 Tomcat 服务器,允许开发人员无需额外配置即可启动一个 Web 应用程序。

8.1 初始化 Spring MVC

在应用程序启动过程中,Spring Boot

会自动配置 Spring MVC 并初始化 DispatcherServlet

@Bean
public DispatcherServlet dispatcherServlet() {return new DispatcherServlet();
}

8.2 启动嵌入式服务器

Spring Boot 支持多种嵌入式服务器,如 Tomcat、Jetty 和 Undertow。在应用程序启动过程中,Spring Boot 会自动启动嵌入式服务器并监听指定端口。

@Bean
public ServletWebServerFactory servletWebServerFactory() {return new TomcatServletWebServerFactory();
}

8.3 CommandLineRunner

CommandLineRunner 接口允许在应用程序启动完成后执行一些自定义逻辑。所有实现 CommandLineRunner 接口的 Bean 会在应用程序启动后被调用。

@Component
public class MyCommandLineRunner implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {// custom logic}
}

结语

通过以上几个方面的详细探讨,我们可以看到 Spring Boot 的启动过程是如何一步步进行的。从初始化 BeanFactory,到实例化和初始化各个 Bean,再到处理单例 Bean 的后续工作,最后启动 HTTP 服务器并准备处理请求。理解这些过程可以帮助我们更好地使用 Spring Boot 进行开发,并在遇到问题时能够快速定位和解决问题。

Spring Boot 的设计理念就是简化开发人员的工作,使得复杂的配置和初始化过程对开发人员透明。这种设计不仅提高了开发效率,也使得代码更加简洁和易于维护。

希望这篇博客能帮助大家更好地理解 Spring Boot 的启动原理,并在实际开发中更好地应用这一强大的框架。

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

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

相关文章

长轮询之websocket

官方文档 背景 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它是为了解决 HTTP 协议存在的一些问题而产生的。WebSocket 的产生背景主要包括以下几点: HTTP 协议的局限性 HTTP 协议是一种请求-响应模型,客户端发起请求,服务端返回响应。这种模型存在一些问题,如…

等级保护测评与风险评估:构建网络安全的双重保障

# 等级保护测评与风险评估&#xff1a;构建网络安全的双重保障 在网络信息技术飞速发展的今天&#xff0c;网络安全问题日益成为社会关注的焦点。等级保护测评和风险评估作为网络安全管理的两个重要环节&#xff0c;对于确保信息系统的安全稳定运行具有重要意义。本文将探讨等级…

Stage #15深度解析:十六进制编码在XSS绕过中的应用

Stage #15深度解析&#xff1a;十六进制编码在XSS绕过中的应用 在网络安全领域&#xff0c;跨站脚本攻击&#xff08;XSS&#xff09;是一种常见的网络攻击手段。随着Web应用安全防护措施的不断完善&#xff0c;攻击者需要更高级的技术来绕过这些防护。本文将详细介绍如何利用…

1782java英语陪学记词系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java英语陪学记词系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助采用了java设计&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用web模式&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&…

AI大底座核心平台:百度百舸AI异构计算平台(AI IaaS)与AI中台(AI PaaS)

AI大底座正是整合了以上端到端全要素技术能力&#xff0c;将基础架构IaaS与应用平台PaaS能力深度融合&#xff0c;面向企业和产业AI生 产与应用的全生命周期提供完整解决方案。 百舸AI异构计算平台是AI IaaS层的核心平台&#xff0c;包括AI计算、AI存储、AI加速、AI容器四层套件…

win磁盘映射到linux

有时虚拟机磁盘不够或文件想存在本地但使用linux环境&#xff0c;可以使用磁盘映射 1.windows磁盘映射&#xff0c;指定文件win_share进行文件共享&#xff0c;右键属性共享 2.linux 新建映射目录win_share 3.在linux进行挂载 sudo mount -t cifs //win7ip地址/win_share /hom…

【k8s的三种探针】

一、探针类型 作用&#xff1a;容器内应用的监测机制&#xff0c;根据不同的探针来判断容器应用当前的状态。 k8s 有三种类型的探针&#xff1a;StartupProbe(启动探针)、LivenessProbe(存活探针)、ReadinessProbe(就绪探针)。它们可以同时存在&#xff0c;但如果有StartupPro…

shell(一)

shell 既是脚本语言又是应用程序 查看自己linux系统的默认解析&#xff1a;echo $SHELL 创建第一个shell 文件 touch 01.sh编辑 vi 01.sh01.sh 文件内容 #!/bin/bash echo felicia保存 按Esc 然后输入:wq 定义以开头&#xff1a;#!/bin/bash #!用来声明脚本由什么shell解释…

idea maven 执行 控制台乱码

这是没加出现的问题 上方案

【HTTP系列】TCP/IP协议

文章目录 一、是什么二、划分五层体系应用层传输层网络层数据链路层物理层 四层体系 三、总结参考文献 一、是什么 TCP/IP&#xff0c;传输控制协议/网际协议&#xff0c;是指能够在多个不同网络间实现信息传输的协议簇 TCP&#xff08;传输控制协议&#xff09; 一种面向连…

【YOLOv5/v7改进系列】替换上采样层为Dysample

一、导言 介绍了一种名为DySample的超轻量级且高效的动态上采样器。DySample旨在解决当前动态上采样技术如CARAFE、FADE和SAPA虽然性能提升显著但带来大量计算负担的问题&#xff0c;这些问题主要来源于动态卷积的时间消耗以及用于生成动态核的额外子网络。此外&#xff0c;FA…

STC90C51驱动LCD1602、LCD12864、OLED

主控芯片&#xff08;STC90C516RDPG5151028&#xff09;介绍 ROM64K,RAM1280字节&#xff0c;40Pin&#xff0c;3个定时器&#xff0c;1个串口&#xff0c;8个中断源&#xff08;分别是&#xff1a;外部中断0(INTO)、外部中断 1(INT1)、外部中断 2(INT2)、外部中断 3(INT3)、定…

系统化自学Python的实用指南

目录 一、理解Python与设定目标 二、搭建学习环境与基础准备 三、入门学习阶段 四、中级进阶阶段 五、项目实践与持续深化 六、持续学习与拓展 一、理解Python与设定目标 Python概述&#xff1a;详细介绍Python的历史沿革、设计理念、主要特点&#xff08;如易读、易维护…

pytest构建和测试FastAPI CURD API

文章目录 概述目标FASTAPI 介绍CRUD API 项目设置freezepipreqs 代码介绍run APIpytest测试F&Q1.执行uvicorn app.main:app --host localhost --port 8000 --reload 报错 zsh: /usr/local/bin/uvicorn: bad interpreter2.生成requirement.txt时&#xff0c;pip3 list pipre…

C语言printf( ) 函数有哪些参数?

一、问题 printf( ) 函数的作⽤是向终端输出若⼲个任意类型的数据&#xff0c;此函数由格式控制部分和输出表列两部分组成&#xff0c;格式控制部分⼜由“&#xff05;”和格式字符串组成&#xff0c;那么&#xff0c;此函数格式字符串部分有哪些参数呢&#xff1f; 二、解答 …

Frida 学习之 messages

目录 一、消息发送 二、环境准备 三、从目标进程中发消息 四、在目标进程中接收消息 五、在目标进程中以阻塞方式接收消息 官方链接&#xff1a;Messages | Frida • A world-class dynamic instrumentation toolkit 参考链接&#xff1a;Frida官方手册 - 消息发送_frida…

Git操作--如何将本地文件夹push到远程新建的仓库中

一、从命令行创建一个新的仓库 1、创建一个说明文件 touch README.md 2、首先使该目录成为git可以管理的目录 git init 3、添加所有文件到本地暂存区 git add . #&#xff08;不要忘了后面的点"."&#xff0c;表示所有文件及目录&#xff09; # git add README…

v-model的工作原理是什么

v-model在Vue.js中是一个非常重要的指令&#xff0c;它实现了表单输入与应用状态&#xff08;data&#xff09;之间的双向绑定。以下是v-model的工作原理&#xff0c;我会尽量以清晰的方式分点表示和归纳&#xff1a; 本质&#xff1a; v-model本质上是一个语法糖&#xff0c…

C语言 RTC时间(年月日时分秒) 和 时间戳 互相转换

一、介绍 在C语言中&#xff0c;将年月日时分秒转换为时间戳&#xff08;Unix时间戳&#xff0c;即从1970年1月1日00:00:00 UTC到现在的秒数&#xff09;通常需要使用struct tm结构体和timegm或mktime函数。&#xff08;注意&#xff0c;mktime函数假设struct tm是本地时间&…

Python语法详解module4(函数)

目录 一、函数基础1. 函数的概念和作用2. 函数的定义和调用3. 参数传递 二、返回值和文档字符串返回值的概念和用法1. 返回值的概念2. 使用 return 关键字返回值&#xff1a;3. 多个返回值的情况&#xff1a; 文档字符串&#xff08;docstring&#xff09;的作用和使用方法1. 文…