Java面试八股之Spring容器的启动流程

  1. Spring容器的启动流程

Spring容器的启动流程涉及一系列有序的操作,以确保容器正确初始化并准备好管理应用程序中的Bean。以下是一个详细的启动流程概述:

1. 加载配置:

资源定位:Spring容器首先需要确定配置资源的位置,这可以是XML配置文件、Java配置类、注解配置或者其他形式的资源。资源定位可以通过编程方式指定,也可以通过Spring Boot的自动配置机制或外部配置(如application.properties)来确定。

解析配置:根据选定的配置方式,Spring容器开始解析配置信息。对于XML配置,使用XML解析器读取并解析文件;对于Java配置类,通过反射机制加载并执行配置类中的方法;对于注解配置,通过类路径扫描找到标记有特定注解(如@Component、@Service、@Repository、@Controller等)的类。

2. 注册Bean定义:

创建BeanDefinition:解析配置信息的过程中,Spring会为每个Bean生成对应的BeanDefinition对象,它包含了Bean的类型、构造方法参数、属性值、初始化方法、依赖关系、作用域、生命周期回调方法等所有相关信息。

BeanDefinition注册:将生成的BeanDefinition对象注册到BeanDefinitionRegistry中,这是一个内部的数据结构(通常是Map),用于存储所有Bean的定义。注册过程中,可能会根据配置进行别名设置、自动装配规则定义等。

3. 预处理与Bean工厂初始化:

预处理:容器可能进行一些预处理操作,如设置容器的状态(如标记为活动状态)、检查运行环境(如日志系统)、初始化容器内部组件(如事件广播器)等。

BeanFactory初始化:创建并初始化BeanFactory或其子类(如DefaultListableBeanFactory),它是Spring容器的核心组件,负责管理和创建Bean。初始化过程中,BeanFactory会根据注册的BeanDefinition创建内部数据结构,为后续Bean的实例化做好准备。

4. Bean的实例化与依赖注入:

非懒加载单例Bean的预实例化:对于非懒加载的单例Bean,Spring容器会在启动时就进行实例化。这通常包括调用构造函数创建Bean实例,然后设置属性值(依赖注入)、执行初始化回调方法(如@PostConstruct)等。

其他作用域Bean的延迟实例化:对于原型(Prototype)或其他非单例作用域的Bean,以及懒加载的单例Bean,它们的实例化过程会在第一次请求时才发生。

5. 后处理与生命周期回调:

Bean后处理器:如果有注册的Bean后处理器(如BeanPostProcessor、InstantiationAwareBeanPostProcessor、SmartInitializingSingleton等),它们会在Bean实例化和初始化完成后执行自定义的逻辑,如进行AOP代理增强、自定义属性填充等。

生命周期回调:执行Bean定义中定义的初始化回调方法(如init-method属性指定的方法)和/或实现了特定生命周期接口(如InitializingBean)的Bean的初始化方法。

6. 容器就绪:

刷新容器:完成上述步骤后,Spring容器调用refresh()方法进行最后的刷新操作,确保所有Bean都已正确初始化。此时,容器对外宣告就绪,可以响应客户端的Bean请求。

事件发布:在容器启动过程中,可能会触发一系列的生命周期事件(如ContextRefreshedEvent),允许其他组件(如监听器)对容器状态变化做出响应。

至此,Spring容器的启动流程完成,应用程序可以通过容器获取所需的Bean并开始执行业务逻辑。在整个过程中,Spring遵循了IoC(控制反转)和DI(依赖注入)原则,确保Bean的创建、配置、组装和管理都在容器的统一控制之下,实现了松耦合和可扩展的软件架构。

如果大家需要视频版本的讲解,欢迎关注我的B站:

相关推荐
m0_5719575828 分钟前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
测开小菜鸟4 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
P.H. Infinity5 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天5 小时前
java的threadlocal为何内存泄漏
java
caridle5 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^5 小时前
数据库连接池的创建
java·开发语言·数据库
苹果醋35 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx