SpringBoot 工程的启动步骤
java
// 1. 启动入口
@SpringBootApplication
public class Application {
public static void main(String[] args) {
// 这是启动的起点
SpringApplication.run(Application.class, args);
}
}完整启动流程图
- 1、启动入口:
SpringApplication.run() - 2、实例化 SpringApplication 对象
- 3、执行 run() 方法
- 4、SpringApplicationRunListeners 开始监听
- 5、准备 Environment
- 6、打印 Banner
- 7、创建 ApplicationContext
- 8、准备 ApplicationContext
- 9、刷新 ApplicationContext(核心!)
- 10、调用 ApplicationRunner/CommandLineRunner
- 11、应用启动完成
详细启动步骤分析
1、启动入口阶段
java
// 1. 启动入口
@SpringBootApplication
public class Application {
public static void main(String[] args) {
// 这是启动的起点
SpringApplication.run(Application.class, args);
}
}
// SpringApplication.run() 方法的内部调用链
public class SpringApplication {
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
// 创建 SpringApplication 实例
return new SpringApplication(primarySources).run(args);
}
}2、SpringApplication 实例化
java
public class SpringApplication {
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 1. 设置 primarySources(主配置类)
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 2. 推断 Web 应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 3. 设置 ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 4. 设置 ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 5. 推断主应用类
this.mainApplicationClass = deduceMainApplicationClass();
}
// 推断 Web 应用类型
private WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", null)
&& !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", null)
&& !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", null)) {
return WebApplicationType.REACTIVE; // WebFlux 应用
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE; // 非 Web 应用
}
}
return WebApplicationType.SERVLET; // Servlet Web 应用
}
public ConfigurableApplicationContext run(String... args) {
// .....
}
}3、运行阶段(run() 方法)
java
public class SpringApplication {
public ConfigurableApplicationContext run(String... args) {
// 1. 创建启动计时器
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 2. 创建引导上下文(Spring Boot 2.4+)
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 3. 配置 headless 模式
configureHeadlessProperty();
// 4. 获取 SpringApplicationRunListeners
SpringApplicationRunListeners listeners = getRunListeners(args);
// 5. 发布 ApplicationStartingEvent
listeners.starting();
try {
// 6. 准备 ApplicationArguments
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 7. 准备 Environment
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 8. 配置忽略的 Bean
configureIgnoreBeanInfo(environment);
// 9. 打印 Banner
Banner printedBanner = printBanner(environment);
// 10. 创建 ApplicationContext
context = createApplicationContext();
// 11. 准备异常报告器
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class },
context
);
// 12. 准备 ApplicationContext
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 13. 刷新 ApplicationContext(核心!)
refreshContext(context);
// 14. 刷新后的处理
afterRefresh(context, applicationArguments);
// 15. 停止计时器
stopWatch.stop();
// 16. 发布 ApplicationStartedEvent
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
// 17. 调用 Runner
callRunners(context, applicationArguments);
// 18. 发布 ApplicationReadyEvent
listeners.ready(context);
} catch (Throwable ex) {
// 处理启动异常
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
return context;
}
}4、环境准备阶段
java
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 1. 创建 Environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 2. 配置 Environment
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 3. 发布 ApplicationEnvironmentPreparedEvent
listeners.environmentPrepared(environment);
// 4. 绑定 Environment 到 SpringApplication
bindToSpringApplication(environment);
// 5. 转换环境(如果不是 CustomEnvironment)
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
// 6. 配置 PropertySources
ConfigurationPropertySources.attach(environment);
return environment;
}
// 创建合适的 Environment
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}5、创建 ApplicationContext
java
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
// 根据 Web 应用类型选择 Context 类
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
} catch (ClassNotFoundException ex) {
throw new IllegalStateException("Unable create a default ApplicationContext", ex);
}
}
// 使用反射创建 ApplicationContext 实例
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
// 默认的 ApplicationContext 类:
// Servlet Web: AnnotationConfigServletWebServerApplicationContext
// Reactive Web: AnnotationConfigReactiveWebServerApplicationContext
// 非 Web: AnnotationConfigApplicationContext6、准备 ApplicationContext
java
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 1. 设置 Environment
context.setEnvironment(environment);
// 2. 后处理 ApplicationContext
postProcessApplicationContext(context);
// 3. 应用 ApplicationContextInitializer
applyInitializers(context);
// 4. 发布 ApplicationContextInitializedEvent
listeners.contextPrepared(context);
// 5. 打印启动信息
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// 6. 获取 BeanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 7. 注册单例 Bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
// 8. 设置允许 Bean 定义覆盖
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// 9. 设置懒加载
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// 10. 加载 Bean 定义
load(context, sources.toArray(new Object[0]));
// 11. 发布 ApplicationPreparedEvent
listeners.contextLoaded(context);
}7、刷新 ApplicationContext(核心!)
java
// AbstractApplicationContext.refresh() - Spring 容器的核心生命周期
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新
prepareRefresh();
// 2. 获取新的 BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备 BeanFactory
prepareBeanFactory(beanFactory);
try {
// 4. 后处理 BeanFactory
postProcessBeanFactory(beanFactory);
// 5. 调用 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 初始化特殊 Bean(由子类实现)
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. 完成 BeanFactory 初始化
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新
finishRefresh();
} catch (BeansException ex) {
// 13. 销毁已经创建的单例 Bean
destroyBeans();
// 14. 取消刷新
cancelRefresh(ex);
throw ex;
} finally {
// 15. 重置公共缓存
resetCommonCaches();
}
}
}refresh() 方法的详细步骤
java
// 步骤1:准备刷新
protected void prepareRefresh() {
// 1.1 设置启动时间和活跃状态
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// 1.2 初始化属性源
initPropertySources();
// 1.3 验证必需属性
getEnvironment().validateRequiredProperties();
// 1.4 存储早期应用事件
this.earlyApplicationEvents = new LinkedHashSet<>();
}
// 步骤2:获取 BeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 2.1 刷新 BeanFactory
refreshBeanFactory();
// 2.2 获取 BeanFactory
return getBeanFactory();
}
// 步骤5:调用 BeanFactoryPostProcessor
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 这是自动装配的关键步骤!
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 5.1 处理 BeanDefinitionRegistryPostProcessor(如 ConfigurationClassPostProcessor)
// 5.2 处理 BeanFactoryPostProcessor
// 5.3 处理 ImportBeanDefinitionRegistrar
}
// 步骤9:onRefresh() - 由子类实现
protected void onRefresh() throws BeansException {
// 对于 Web 应用,这里会创建 WebServer
// ServletWebServerApplicationContext 会在这里创建并启动 Tomcat/Jetty/Undertow
}
// 步骤11:完成 BeanFactory 初始化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 11.1 初始化 ConversionService
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)) {
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class);
}
// 11.2 注册默认的嵌入值解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 11.3 尽早初始化 LoadTimeWeaverAware Bean
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 11.4 停止使用临时类加载器
beanFactory.setTempClassLoader(null);
// 11.5 缓存所有 Bean 定义元数据
beanFactory.freezeConfiguration();
// 11.6 实例化所有剩余的单例 Bean(核心!)
beanFactory.preInstantiateSingletons();
}8、调用 Runner
java
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
// 1. 获取所有 ApplicationRunner
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
// 2. 获取所有 CommandLineRunner
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
// 3. 排序(使用 @Order 注解)
AnnotationAwareOrderComparator.sort(runners);
// 4. 调用所有 Runner
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try {
runner.run(args);
} catch (Exception ex) {
throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
}
}关键扩展点分析
1、ApplicationContextInitializer
在 ApplicationContext 刷新之前进行自定义初始化
java
public class CustomApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("【ApplicationContextInitializer】自定义初始化");
// 1. 设置环境属性
ConfigurableEnvironment environment = applicationContext.getEnvironment();
environment.getPropertySources().addFirst(new MyPropertySource());
// 2. 注册自定义 Bean
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext;
registry.registerBeanDefinition("customBean",
BeanDefinitionBuilder.genericBeanDefinition(CustomBean.class).getBeanDefinition());
// 3. 修改 BeanFactory 配置
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
beanFactory.addBeanPostProcessor(new CustomBeanPostProcessor());
}
}
// 注册方式:
// 1. 在 META-INF/spring.factories 中:
// org.springframework.context.ApplicationContextInitializer=com.example.CustomApplicationContextInitializer
//
// 2. 通过 SpringApplication.addInitializers() 添加2、ApplicationListener
监听 Spring Boot 启动事件
java
@Component
public class CustomApplicationListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
// 监听所有应用事件
if (event instanceof ApplicationStartingEvent) {
System.out.println("【事件】应用开始启动");
} else if (event instanceof ApplicationEnvironmentPreparedEvent) {
System.out.println("【事件】环境准备完成");
} else if (event instanceof ApplicationContextInitializedEvent) {
System.out.println("【事件】ApplicationContext 初始化完成");
} else if (event instanceof ApplicationPreparedEvent) {
System.out.println("【事件】ApplicationContext 准备完成");
} else if (event instanceof ApplicationStartedEvent) {
System.out.println("【事件】应用启动完成");
} else if (event instanceof ApplicationReadyEvent) {
System.out.println("【事件】应用准备就绪,可以接收请求");
} else if (event instanceof ApplicationFailedEvent) {
System.out.println("【事件】应用启动失败");
}
}
}特定事件监听器
java
@Component
public class EnvironmentPreparedListener
implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
SpringApplication application = event.getSpringApplication();
// 可以在这里修改环境配置
Map<String, Object> defaultProperties = new HashMap<>();
defaultProperties.put("custom.property", "value");
application.setDefaultProperties(defaultProperties);
}
}3、BeanFactoryPostProcessor
在 BeanFactory 准备完成后,Bean 实例化之前修改 Bean 定义
java
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
System.out.println("【BeanFactoryPostProcessor】处理 BeanFactory");
// 1. 获取所有 Bean 定义
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
// 2. 修改 Bean 定义
if (beanDefinition.getBeanClassName() != null &&
beanDefinition.getBeanClassName().contains("Service")) {
// 修改 Service 类的作用域
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
// 添加属性值
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.add("customProperty", "customValue");
}
// 3. 注册新的 Bean 定义
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
if (!registry.containsBeanDefinition("customBean")) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(CustomBean.class);
registry.registerBeanDefinition("customBean", builder.getBeanDefinition());
}
}
}
}
}4、BeanPostProcessor
在 Bean 初始化前后进行处理
java
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
// Bean 初始化之前调用
if (bean instanceof InitializingBean) {
System.out.println("【BeanPostProcessor】Bean 初始化前: " + beanName);
}
// 可以返回包装后的 Bean
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
// Bean 初始化之后调用
if (bean instanceof Aware) {
System.out.println("【BeanPostProcessor】Bean 初始化后: " + beanName);
}
// AOP 代理通常在这里创建
if (bean.getClass().isAnnotationPresent(Transactional.class)) {
// 创建事务代理
return createTransactionProxy(bean);
}
return bean;
}
}性能优化点
1、启动性能优化配置
java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
// 1. 延迟初始化(Spring Boot 2.2+)
app.setLazyInitialization(true);
// 2. 排除不需要的自动配置
app.setBannerMode(Banner.Mode.OFF);
// 3. 设置特定的 Web 应用类型
app.setWebApplicationType(WebApplicationType.SERVLET);
// 4. 优化日志级别
System.setProperty("logging.level.root", "WARN");
System.setProperty("logging.level.org.springframework", "WARN");
app.run(args);
}
}2、配置优化
java
@Configuration
public class StartupOptimizationConfig {
// 1. 使用 @Configuration(proxyBeanMethods = false)
@Configuration(proxyBeanMethods = false) // 避免 CGLIB 代理
public static class OptimizedConfig {
// 配置类
}
// 2. 懒加载 Bean
@Bean
@Lazy
public ExpensiveBean expensiveBean() {
return new ExpensiveBean();
}
// 3. 排除不必要的扫描
@ComponentScan(
excludeFilters = @ComponentScan.Filter(
type = FilterType.REGEX,
pattern = "com.example.exclude.*"
)
)
public static class SelectiveScanConfig {
// 选择性扫描
}
}
朔风