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

SpringBoot面试题01-ApplicationContextInitializer

核心面试题一览

一、ApplicationContextInitializer


1-1、ApplicationContextInitializer是什么?

ApplicationContextInitializerSpring Boot 在启动的时候,在 ApplicationContext(Spring 容器)创建完但还没做 Bean 初始化之前,执行的一段“提前准备逻辑”。

通俗点说:

它让你有机会 Spring 容器真正开始工作之,先插一句话,对容器做一些定制化处理。


1-2、为什么需要这个东西?

有时候我们想:

  • 在所有 Bean 加载之前修改一些配置

  • 动态添加属性,让项目根据外部条件自动变化

  • 在 Bean 初始化前注册一些全局组件

  • 做一些环境检查,比如判断当前是测试环境还是生产环境

但这个时候 Bean 还没创建好,我们不能直接用 @Bean @Autowired 那些东西

所以就需要一种“比 Bean 更早执行”的东西——这就是 ApplicationContextInitializer


1-3、它什么时候执行?

Spring Boot 启动顺序中:

启动 Spring Boot →
创建 ApplicationContext →
(此时 Bean 还没加载)
→ 执行 ApplicationContextInitializer
→ 开始加载 Bean → 项目启动成功

注意重点:它在 Bean 加载之前执行


1-4、怎么用?(最简单的例子)

① 写一个类实现接口

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;public class MyAppInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext context) {System.out.println(">>> ApplicationContextInitializer: 容器创建好了,但 Bean 还没加载");// 比如给环境添加一个属性context.getEnvironment().getSystemProperties().put("myKey", "myValue");}
}

② 告诉 Spring Boot 使用它(注册

resources/META-INF/spring.factories 文件中写:

org.springframework.context.ApplicationContextInitializer=\
com.example.demo.MyAppInitializer

(Spring Boot 就会自动在启动时加载它)

面试官会重点问:怎么注册? 你记住这个就行。


1-5、它能干啥?举两个常用场景

场景 1:根据环境动态改变配置

String profile = context.getEnvironment().getActiveProfiles()[0];
if ("prod".equals(profile)) {context.getEnvironment().getSystemProperties().put("logging.level.root", "ERROR");
}

效果:线上环境只打印 Error,减少日志压力。


场景 2:提前检查系统状态(如 Redis、数据库、配置文件)

if (!new File("/important/config.yml").exists()) {throw new RuntimeException("关键配置文件不存在,项目不允许启动!");
}

让项目安全而不是启动后报错。


1-6、面试官可能问的问题(附标准回答)

Q1:ApplicationContextInitializer 的作用是什么?

它用于在 Spring 容器刷新之前,对 ApplicationContext 进行提前定制,比如动态修改配置、注册组件、校验环境等。


Q2:它的执行时机是什么?

它在 ApplicationContext 创建好Bean 初始化之前执行,属于早期扩展点。


Q3:怎么注册 ApplicationContextInitializer?

META-INF/spring.factories 中通过
org.springframework.context.ApplicationContextInitializer=你的类全限定名 注册。


1-7、总结成一句话

ApplicationContextInitializer 是在 Spring 容器创建后Bean 加载前执行的扩展点,用来在项目启动初期对 ApplicationContext 做定制,比如修改环境配置或检查运行条件。


1-8、示例:给上下文环境对象context注入环境属性

【注意】:

spring.factories文件要自己创建:

示例:

代码讲解:

1、这段代码的作用是:

在 Spring 容器启动之前,往 Spring 的 Environment(环境配置)里手动添加一个自定义的属性来源。

具体来说,它添加了一条配置:

applicationName = big-event

这样之后,你在项目任何地方都可以通过:

@Value("${applicationName}")
private String appName;

或者:

environment.getProperty("applicationName")

来获取这个值。


2、为什么要这样做?

有时候,配置不是写死在配置文件里的,而是要根据运行环境,动态生成,比如:

  • 读取外部系统信息

  • 动态决定项目名称/版本

  • 从数据库或远程配置中心加载参数

  • 根据机房、区域、IP 动态决定配置

这时就可以利用 ApplicationContextInitializer 来提前往 Spring 环境里写配置


3、按代码行解释
public void initialize(ConfigurableApplicationContext applicationContext) {

当 Spring 容器刚创建好,但 Bean 还没加载时,会调用这个方法。


Map<String,Object> myMap = new HashMap<>();
myMap.put("applicationName", "big-event");

准备了一组 你想注入到 Spring 配置环境中的键值对


ConfigurableEnvironment environment = applicationContext.getEnvironment();

获取 环境对象相当于读取 application.yml、system env、JVM 参数的地方。


MutablePropertySources propertySources = environment.getPropertySources();

获取 所有配置的来源 的管理器,比如:

  • 系统环境变量

  • application.yml

  • application.properties

  • 命令行参数

  • 你手动添加的 Map


propertySources.addLast(new MapPropertySource("myMap", myMap));

把你创建的 Map 作为一个 新的配置来源 加进 Spring 配置系统。

addLast 代表优先级最低,意思是:如果 application.yml 中也写了同名配置,则 yml 的会覆盖这个 Map。


4、简单总结一句话(面试官最爱听的)

这段代码利用 ApplicationContextInitializer 在 Bean 初始化前,把一组 Map 类型的自定义配置注入到 Spring 的 Environment 中,使它能像 application.yml 一样被获取和使用。


5、面试官追问:为什么放到 Environment 里,而不是直接写配置文件?

你可以这样回答:

因为有些配置动态生成,不是固定写死的,必须在 Spring 容器启动前提前注入,而 ApplicationContextInitializer 就是专门用来做这种启动早期运行逻辑的扩展点。


测试使用注入的自动以环境属性:

小结:

二、真实企业级场景


2-1、企业级真实场景:多环境动态加载租户(Tenant)配置

假设你现在做的是 SaaS 多租户系统(一个系统服务多个客户 / 企业)。

每个客户有自己:

  • 数据库地址

  • Redis 前缀

  • 系统名称

  • Logo、主题等配置

但是这些信息不能写死在 application.yml 里,因为每个客户都不同,而且可能会变化。

而且这些信息必须要在Spring 容器初始化前就准备好,否则后面 Bean(特别是 DataSource、RedisTemplate)初始化会失败。


这时我们就会这样做:

ApplicationContextInitializer 里:

  1. 读取租户 ID(可能来自域名、请求头、部署参数等)

  2. 根据租户 ID 查询数据库 / Nacos / Redis 中存储的租户配置

  3. 将这些配置注入到 Spring Environment
    让 Spring 后面创建 Bean 时自动使用这些动态配置


1、示例代码

public class TenantConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext context) {// 1. 根据运行参数获取租户 ID,例如部署时指定 -DtenantId=abcString tenantId = context.getEnvironment().getProperty("tenantId");// 2. 从数据库或配置中心加载租户配置(伪代码)Map<String, Object> tenantConfig = TenantConfigService.loadConfig(tenantId);// 3. 注入到 Spring 环境中ConfigurableEnvironment environment = context.getEnvironment();environment.getPropertySources().addFirst(new MapPropertySource("tenantConfig", tenantConfig));}
}

2、效果是什么?

之后在任何地方都可以这样写:

@Value("${datasource.url}")
private String dbUrl;

并且不同租户的数据源不需要改代码、不需要改配置文件,就能自动切换


3、小结:

在企业里,我们一般会利用 ApplicationContextInitializer 来进行一些启动早期的动态配置操作
比如在 SaaS 多租户系统中,我们需要根据租户 ID 动态加载不同的数据库连接、Redis 配置信息、系统名称等,而这些配置必须在 Spring 创建 Bean 之前准备好,所以我们会在 ApplicationContextInitializer 里从数据库或配置中心加载租户配置,并注入到 Environment 中,这样后续 Bean 初始化就会自动使用对应租户配置,实现真正的动态、多租户配置加载。


2-2、 2 个企业常用场景

场景描述ApplicationContextInitializer 做啥
灰度发布 / 蓝绿部署不同机器跑不同配置启动前根据机器标签注入特定开关
多机房 / 多地区部署不同 region 使用不同资源启动时判断地区 → 动态注入资源配置

你现在应该这样理解它:

ApplicationContextInitializer = 在 Spring 容器真正开始工作前,执行一段提前注入或修改配置的逻辑。

而这东西最大用途就是:配置是动态的,不是在 yml 里写死的。


三、SaaS 系统扫盲

3-1、什么是 SaaS 系统?

SaaS 的全称是 Software as a Service,翻译叫:

软件即服务

什么意思?

以前软件是 买断 + 安装本地服务器 的,比如:

  • 公司自己买服务器

  • 自己部署系统

  • 自己维护升级

这种叫 传统软件模式,又贵又麻烦。


SaaS 系统是把软件放在云端,用户只要:

  • 打开浏览器

  • 输账号密码

就能直接用。

无需安装、无需部署、无需维护。

SaaS 就像你用微信、钉钉、飞书、企业微信一样,点一下就能用。


3-2、一句话总结:

模式描述
传统软件软件买回去,自己安,自己养,自费修
SaaS软件放云上,按月/按年订阅,厂商负责维护

3-3、为什么企业喜欢 SaaS?

因为:

✅ 不用买服务器
✅ 不用请专业运维
✅ 不用自己升级系统
✅ 不用担心安全补丁
✅ 成本低、上线快

你只要付 订阅费 就能用。


3-4、SaaS 和普通网站有什么区别?

普通网站:所有人用同一套系统

比如:

  • Bilibili

  • 淘宝

  • 抖音

大家都用同一个系统,数据也都存在一起。


SaaS 系统:一个系统服务很多不同公司,每家公司有自己的数据和配置

核心特点:

同一个系统 → 面向多个不同客户(租户) → 数据隔离

例如:

公司系统里看到的内容
A 公司A 的员工 / 客户 / 订单
B 公司B 的员工 / 客户 / 订单
C 公司C 的员工 / 客户 / 订单

同一个系统,不同公司看不见彼此。


3-5、举个SaaS 系统的例子

产品是不是 SaaS?说明
企业微信✅ 是一个系统服务不同公司,登录后看到自己公司
钉钉✅ 是公司之间数据隔离
飞书✅ 是同理
12306❌ 不是所有人数据混在一起,不分租户公司

3-5、回到我们刚才说 ApplicationContextInitializer 的场景

SaaS 系统里,每个客户可能需要:

  • 不同数据库

  • 不同主题皮肤

  • 不同系统名称

  • 不同菜单功能开关

而这些东西必须在 Spring 容器还没初始化 Bean 前 注入,所以才需要:

ApplicationContextInitializer

提前把租户配置放到 Environment 中

这样后续整个系统会“自动适配该租户”。

http://www.dtcms.com/a/544945.html

相关文章:

  • java之Future
  • Projection Error: Explanation and Causes 关于投影误差的解释与说明
  • php网站开发模板织梦移动端网站模板下载地址
  • 【JavaEE初阶】TCP的核心机制6——拥塞控制
  • LangChain4j学习一:聊天和语言模型
  • LeetCode hot100:056 合并区间:高效算法解析
  • uni-app开发入门手册
  • 做网站属于程序员吗网站搭建php源码
  • 什么是支架电容,它的原理是什么
  • 仓颉UI开发精髓:构建高复用、可组合的自定义组件
  • 校园文化宣传主题网站的建设做门户网站多少钱
  • 深入理解 Rust 的 Iterator Trait:惰性与抽象的力量
  • vs做网站怎么加文件夹商丘销售网站制作
  • 自定义ViewGroup实现要点
  • docker学习笔记,从入门开始!
  • 从 MVC 5 到 Core MVC:ASP.NET MVC 框架的 “进化之路“
  • 认识人工智能与大模型应用开发
  • 电子学会青少年机器人技术(一级)等级考试试卷-实操题(2025年9月)
  • 亲 怎么给一个网站做备份哪些专业能建网站
  • JWT 全面解析与 Spring Boot 实战教程
  • 【预览PDF】前端预览pdf
  • 【PrintPDF】PrintPDF Cargo.toml 分析
  • R/3 销售与分销
  • 唐山微网站建设价格网站建设信息发布
  • 做的最好的理财网站国内无版权图片网站
  • GXDE OS 支持在 WSL 上使用了(带桌面环境)
  • 【Linux】基础指令(2):理解Linux的指令和核心概念
  • Rust 借用分割技巧:安全解构复杂数据结构
  • 在Vue项目中平滑地引入HTML文件
  • 1688网站特点石家庄模板网站建设