SpringBoot启动源码剖析:从入口到容器的诞生
文章目录
- SpringBoot启动的核心入口
- SpringApplication的初始化
- SpringBoot的启动流程
- 1. 准备环境(Environment)
- 2. 创建应用上下文(ApplicationContext)
- 3. 刷新应用上下文(Refresh Context)
- 4. 调用Runner接口
- SpringBoot启动的核心机制
- 1. 自动配置(Auto-Configuration)
- 2. 条件注解(Conditional Annotations)
- 3. SpringFactoriesLoader
- 总结
SpringBoot作为Java开发中最流行的框架之一,以其“约定优于配置”的理念深受开发者喜爱。但你是否好奇过,SpringBoot是如何启动的?它的内部机制是什么?今天,我们就从源码的角度,深入剖析SpringBoot的启动过程。
SpringBoot启动的核心入口
SpringBoot的启动入口是SpringApplication.run()
方法。无论是通过main
方法启动,还是通过其他方式,最终都会调用这个方法。下面是一个典型的SpringBoot启动代码:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
接下来,我们将从SpringApplication.run()
方法开始,逐步分析SpringBoot的启动流程。
SpringApplication的初始化
SpringApplication.run()
方法的核心逻辑在SpringApplication
类中。我们先来看一下SpringApplication
的初始化过程:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
这段代码主要做了以下几件事:
- 设置主配置类(
primarySources
)。 - 推断应用类型(
webApplicationType
),比如是Servlet应用还是Reactive应用。 - 加载
BootstrapRegistryInitializer
、ApplicationContextInitializer
和ApplicationListener
等组件。
SpringBoot的启动流程
1. 准备环境(Environment)
SpringBoot在启动时,首先会准备运行环境。这一步的核心代码如下:
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
prepareEnvironment
方法会加载配置文件(如application.properties
),并将配置信息封装到Environment
对象中。
2. 创建应用上下文(ApplicationContext)
接下来,SpringBoot会根据应用类型创建对应的ApplicationContext
。例如,对于Web应用,会创建AnnotationConfigServletWebServerApplicationContext
。
context = createApplicationContext();
3. 刷新应用上下文(Refresh Context)
这是SpringBoot启动过程中最核心的一步。refreshContext
方法会触发Spring容器的初始化,包括Bean的加载、依赖注入、AOP代理等。
refreshContext(context);
refresh
方法的源码如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
} catch (BeansException ex) {
destroyBeans();
cancelRefresh(ex);
throw ex;
}
}
}
4. 调用Runner接口
在容器初始化完成后,SpringBoot会调用CommandLineRunner
和ApplicationRunner
接口的实现类。这些接口通常用于执行一些启动后的任务。
callRunners(context, applicationArguments);
SpringBoot启动的核心机制
1. 自动配置(Auto-Configuration)
SpringBoot的自动配置是通过@EnableAutoConfiguration
注解实现的。它会根据类路径下的依赖,自动加载相应的配置类。例如,如果引入了spring-boot-starter-web
,SpringBoot会自动配置Tomcat和Spring MVC。
2. 条件注解(Conditional Annotations)
SpringBoot大量使用了条件注解(如@ConditionalOnClass
、@ConditionalOnMissingBean
),这些注解决定了某个配置类是否生效。例如:
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })
public class TomcatAutoConfiguration {
// 自动配置Tomcat
}
3. SpringFactoriesLoader
SpringBoot通过SpringFactoriesLoader
加载META-INF/spring.factories
文件中的配置类。这是SpringBoot扩展机制的核心。
总结
通过以上分析,我们可以看到,SpringBoot的启动过程是一个复杂但有序的过程。从环境准备到容器刷新,再到自动配置和Runner调用,每一步都体现了SpringBoot设计的精妙之处。
如果你对SpringBoot的源码感兴趣,可以尝试下载SpringBoot的源码,结合本文的分析,深入探索其中的奥秘。相信你会对SpringBoot有更深刻的理解!
关于作者
我是双非二本从创业公司一路杀到中厂的程序员,喜欢研究技术底层原理。如果你也对技术感兴趣,欢迎关注我的CSDN博客,我们一起交流学习!