数码之家
第二套高阶模板 · 更大气的阅读体验

Spring Boot框架核心源码解读:从启动类到自动配置的真相

发布时间:2026-02-10 21:21:33 阅读:2 次

上周帮公司IT同事排查一个线上服务启动慢的问题,查到最后发现是某个自定义Starter里重复加载了DataSourceAutoConfiguration。这事儿让我又翻了一次Spring Boot的启动源码——原来我们天天写的@SpringBootApplication,背后真没那么简单。

main方法之后发生了什么?

你写完public static void main(String[] args) { SpringApplication.run(App.class, args); },按下回车,控制台刷出一堆INFO日志。但SpringApplication.run()干了啥?不是黑盒,它就藏在spring-boot包里。

点进去看,核心逻辑在SpringApplication#run方法里:先是准备环境(environment),再创建ApplicationContext,最后刷新上下文(refreshContext)。最关键的refreshContext(),会一路调用到AbstractApplicationContext#refresh(),这里才是Spring容器真正“活过来”的地方。

@SpringBootApplication到底合并了啥?

这个注解看着轻巧,其实是三个注解的组合:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

其中@EnableAutoConfiguration最值得细看。它通过SpringFactoriesLoader.loadFactoryNames()去META-INF/spring.factories里找org.springframework.boot.autoconfigure.EnableAutoConfiguration下的所有自动配置。比如spring-boot-autoconfigure.jar里就写着:

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration

这些类不是全都被加载,而是按条件筛选。比如DataSourceAutoConfiguration上标着@ConditionalOnClass(DataSource.class),意味着只有classpath里有DataSource类(比如HikariCP或Druid)时,这个配置才生效。

自动配置里的“条件开关”怎么工作的?

以RedisAutoConfiguration为例,它上面有这么一行:

@ConditionalOnClass({ RedisOperations.class })

Spring Boot启动时会通过ConditionEvaluator判断这个条件是否成立。原理很简单:用ClassLoader尝试加载RedisOperations这个类,能加载成功就继续,否则跳过整个配置类。这种机制让自动配置既灵活又安全,不会因为少引一个依赖就直接报错退出。

再比如你项目里没配spring.redis.host,默认情况下RedisAutoConfiguration虽然被扫描到了,但内部的LettuceConnectionConfiguration因为@ConditionalOnMissingBean(RedisConnectionFactory.class)而不会生效——直到你手动加了配置,条件满足,连接工厂才真正创建出来。

动手验证:删掉spring.factories试试

你可以自己做个实验:新建一个空的starter模块,在resources/META-INF/spring.factories里只写一行:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.demo.MyTestAutoConfiguration

然后写个极简的MyTestAutoConfiguration,里面只注册一个String Bean。启动后用@Autowired注入试试,你会发现它真的进容器了。这就是自动配置最朴素的样子——没有魔法,只有约定和反射。

办公网络环境里,很多中间件集成(比如LDAP认证、RabbitMQ连接池、Prometheus监控端点)都靠这套机制实现“开箱即用”。理解了源码这一层,下次遇到自动配置不生效,你就知道该去看日志里的ConditionEvaluationReport,而不是盲目改yml。