SpringBoot启动 → 自动配置 → Starter 追问链#
追问路径#
Q: SpringBoot应用是怎么启动起来的?
→ SpringApplication.run():推断应用类型→加载ApplicationContextInitializer/Listener→准备Environment→创建容器→refresh()→启动内嵌Tomcat
Q: @SpringBootApplication这个注解做了什么?
→ 三合一:@SpringBootConfiguration(配置类) + @EnableAutoConfiguration(开自动配置) + @ComponentScan(包扫描)
Q: 自动配置的核心机制是什么?
→ @EnableAutoConfiguration靠@Import导入AutoConfigurationImportSelector,加载META-INF下的自动配置类清单
├─ Q: 自动配置类清单从哪读?SpringBoot2和3有区别吗?
│ → 2.x读spring.factories的EnableAutoConfiguration键;2.7+/3.x改用AutoConfiguration.imports文件(SPI演进)
│ Q: 为什么引入一个依赖(如spring-boot-starter-web)就自动配好了?
│ → starter只是依赖聚合(空jar),真正的autoconfigure包里有配置类,靠条件注解按需生效
│ Q: 条件注解怎么做到"按需"装配?
│ → @ConditionalOnClass(有这个类才配)/@ConditionalOnMissingBean(用户没定义才用默认)/@ConditionalOnProperty等
│ Q: 用户自定义的Bean怎么覆盖默认配置?
│ → 自动配置类标@ConditionalOnMissingBean,用户一旦自己定义同类型Bean,默认的就不生效,实现"约定优于配置"
└─ Q: 自己怎么写一个starter?
→ 建autoconfigure模块写@AutoConfiguration配置类+条件注解+@ConfigurationProperties,注册到AutoConfiguration.imports
Q: @Configuration的proxyBeanMethods有什么用?
→ true(默认)时配置类被CGLIB代理,@Bean方法互相调用返回同一单例;false(Lite模式)不代理、启动快但方法调用是普通new
Q: SpringBoot启动慢/想加速怎么办?
→ 排查自动配置(--debug看Conditions报告)、按需排除、用Lite模式、AOT/GraalVM Native提前编译plaintext涉及知识点#
- SpringBoot启动流程 — run()的完整生命周期
- SpringBoot自动配置原理 — @EnableAutoConfiguration与ImportSelector
- SpringBoot-Starter原理 — 依赖聚合与autoconfigure分离
- Configuration类代理机制 — proxyBeanMethods与Full/Lite模式
- Spring常用注解总结 — 条件注解与组合注解
- Spring-IoC原理 — 容器refresh与Bean注册
- Bean生命周期 — 自动配置Bean的初始化
- Spring-BeanFactory与ApplicationContext — 容器层次与启动
核心串联逻辑#
- 启动主线:
SpringApplication.run()推断类型→准备环境→创建并refresh容器→启动内嵌容器,期间触发各类Listener事件 - 三合一注解:
@SpringBootApplication= 配置类 + 自动配置 + 包扫描 - 自动配置链路:
@EnableAutoConfiguration→@Import选择器→读AutoConfiguration.imports(旧版spring.factories)→拿到一堆配置类 - 按需生效靠条件注解:
@ConditionalOnClass判断依赖在不在、@ConditionalOnMissingBean实现”用户优先”,这就是”约定优于配置”的底层 - Starter职责分离:starter是空的依赖聚合包,autoconfigure包才放配置类,二者分开便于复用
- 代码示例:
java// 一个典型的自动配置类 @AutoConfiguration @ConditionalOnClass(RedisTemplate.class) // classpath有Redis才配 @EnableConfigurationProperties(RedisProperties.class) public class RedisAutoConfiguration { @Bean @ConditionalOnMissingBean // 用户没自定义才用默认 public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory f) { RedisTemplate<Object, Object> t = new RedisTemplate<>(); t.setConnectionFactory(f); return t; } }
面试回答串联#
30秒速答#
“SpringApplication.run()推断应用类型、准备环境、创建容器refresh、启动内嵌Tomcat。@SpringBootApplication是配置类+自动配置+包扫描三合一。自动配置靠@EnableAutoConfiguration导入选择器,读AutoConfiguration.imports清单(老版本是spring.factories),再用@ConditionalOnClass、@ConditionalOnMissingBean这些条件注解按需装配,实现约定优于配置。Starter只是依赖聚合,真正配置在autoconfigure包里。“
2分钟展开答#
“SpringBoot启动入口是SpringApplication.run(),它先推断应用类型(普通/Web/响应式),加载ApplicationContextInitializer和Listener,准备Environment读配置,创建对应的ApplicationContext,调refresh()完成Bean注册和初始化,最后启动内嵌Tomcat,整个过程通过事件机制把各扩展点串起来。核心注解@SpringBootApplication是三个注解的组合:@SpringBootConfiguration标识配置类、@ComponentScan做包扫描、@EnableAutoConfiguration开启自动配置。自动配置是SpringBoot的灵魂:@EnableAutoConfiguration通过@Import导入AutoConfigurationImportSelector,它去读META-INF下的自动配置清单——SpringBoot2.x读spring.factories里EnableAutoConfiguration这个key,2.7和3.x改成了AutoConfiguration.imports文件,本质都是SPI机制。拿到几十上百个自动配置类后,并不是全都生效,而是靠条件注解按需装配:@ConditionalOnClass判断某个类在不在classpath、@ConditionalOnProperty判断配置开关、最关键的@ConditionalOnMissingBean——用户一旦自己定义了同类型的Bean,默认配置就不生效,这就是’约定优于配置’同时又允许覆盖的底层原理。Starter本身是个几乎空的依赖聚合包,真正的配置类在对应的autoconfigure包里,两者分离是为了复用。自己写starter就是建autoconfigure模块写@AutoConfiguration配置类配合条件注解和@ConfigurationProperties,再注册到imports文件。另外@Configuration的proxyBeanMethods默认true会用CGLIB代理保证@Bean方法互调拿到同一单例,设false是Lite模式启动更快。排查启动可以用—debug看Conditions评估报告。“
相关追问链#
- Spring-IoC-AOP-事务-循环依赖追问链 — 容器refresh与Bean生命周期
- JVM类加载-双亲委派-字节码追问链 — SPI与spring.factories的类加载
- 微服务注册-熔断-限流-链路追问链 — SpringCloud基于SpringBoot自动配置扩展
- 项目经验-技术选型-问题排查追问链 — 框架选型与启动优化