springboot启动流程详解_网页解析的详细过程

springboot启动流程详解_网页解析的详细过程文章目录 前言 一 SpringBoot 特性 二 配置形式 1 应用主入口 1 定义 Bean 2 Configuratio 类配置 3 Spring xml 配置 3 AutoConfigur 类配置 三 启动流程 1 流程图 3 Bean 定义加载顺序 思考总结 最后 前言 此文章讲解 SpringBoot 中配置 Bean 的几种形式

----

文章目录

前言

一、SpringBoot特性

二、配置形式

1.应用主入口

1.定义Bean

2.Configuration类配置

3. Spring xml配置

3.AutoConfiguration类配置

三、启动流程

1.流程图

3.Bean定义加载顺序

思考总结

最后

----

前言

此文章讲解SpringBoot中配置Bean的几种形式,以及在SpringBoot启动流程中的先后顺序。

----

一、SpringBoot特性

Spring核心特性和概念:


SpringBoot核心特型:

约定大于配置
提供了默认的编码Bean配置扫描机制,默认的WebServer启动机制,默认的三方包Bean加载配置机制等等。

Java代码定义配置Bean

二、配置形式

1.应用主入口

@SpringBootApplication
@ImportResource(locations = {"classpath:spring-config.xml"})
public class TestWebApp {
public static void main(String[] args) {
SpringApplication.run(TestWebApp.class, args);
}
}

@SpringBootApplication注解是一个组合注解,主要由@SpringBootConfiguration,@EnableAutoConfiguration和@ComponentScan这三个注解组合而成。
因此@SpringBootApplication注解主要作为一个配置类,能够触发包扫描和自动配置的逻辑,从而使得SpringBoot的相关bean被注册进Spring容器。

1.定义Bean

@RestController
public class HelloController {
}

@Service
public class TestService {
}

2.Configuration类配置

@Configuration
public class TestConfiguration {
@Bean
public TestConfigBean testConfig() {
return new TestConfigBean();
}
}

3. Spring xml配置

    

3.AutoConfiguration类配置

在二方包模块中的resources/META-INF/spring.factories文件中按照如下格式注册AutoConfiguration类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.wei.spring.autoconfig.TestAutoConfigurationA,\
com.wei.spring.autoconfig.TestAutoConfigurationB

二方包模块中定义AutoConfiguration类

@Configuration
public class TestAutoConfigurationA {
@Bean
public AutoBeanA autoBeanA() {
return new AutoBeanA();
}
}

@Configuration
@AutoConfigureAfter(TestAutoConfigurationA.class)
public class TestAutoConfigurationB {
@Bean
@ConditionalOnBean(value = AutoBeanA.class)
public AutoBeanB autoBeanB(AutoBeanA autoBeanA) {
return new AutoBeanB(autoBeanA);
}
}

在主应用的pom.xml引入二方包,spring就会进行自动装载

        
com.test
spring-demo-autoconfig
1.0-SNAPSHOT

/pre>

h2>三、启动流程

/h2>

h3>1.流程图

/h3>

p>SpringApplicationRunListener::starting发布开始启动事件

/p>

p>ApplicationListener::onApplicationEvent发布ApplicationStartingEvent

/p>

p>prepareEnvironment准备环境,创建Environment,配置PropertySources和Profile

/p>

p>getOrCreateEnvironment获取Environment

/p>

p>configureEnvironment配置Environment

/p>

p>configurePropertySources设置PropertySources

/p>

p>configureProfiles设置Profile

/p>

p>SpringApplicationRunListener::environmentPrepared发布environmentPrepared

/p>

p>ApplicationListener::onApplicationEvent发布ApplicationEnvironmentPreparedEvent

/p>

p>createApplicationContext创建ApplicationContext

/p>

p>prepareContext在Context执行前,进行准备工作,配置

/p>

p>ApplicationContextInitializer::initialize扩展点,调用自定义注册的ApplicationContextInitializer的initialize方法,对ApplicationContext进行自定义设置

/p>

p>SpringApplicationRunListener::contextPrepared发布contextPrepared

/p>

p>ApplicationListener::onApplicationEvent发布ApplicationContextInitializedEvent

/p>

p>load(ConfigurableApplicationContext)装载ApplicationContext,包括启动类

/p>

p>BeanDefinitionLoader::load加载Bean定义(SpringBootApplication主程序类)

/p>

p>SpringApplicationRunListener::contextLoaded发布事件

/p>

p>ApplicationListener::onApplicationEvent发布ApplicationPreparedEvent

/p>

p>refreshContext刷新Context,Context主流程

/p>

p>prepareRefresh准备刷新的上下文环境,系统属性,环境变量

/p>

p>obtainFreshBeanFactory获取BeanFactory并初始化,Bean配置读取解析,定制功能包括@Qualifier和@Autowired

/p>

p>prepareBeanFactory对BeanFactory进行功能填充,SpEL,属性编辑器,AspectJ等

/p>

p>postProcessBeanFactory后置处理BeanFacotry,扩展点,空函数

/p>

p>invokeBeanFactoryPostProcessors激活各种BeanFacotry处理器,操作BeanDefinition

/p>

p>按照硬编码,PriorityOrdered注解,Ordered注解,以及剩余的的BeanDefinitionRegistryPostProcessor::postProcessBeanDefinitionRegistry

/p>

p>执行SpringBoot扩展注册的ConfigurationClassPostProcessor,用于实现SpringBoot核心的代码注册Bean的功能

/p>

p>循环解析ConfigurationClass

/p>

p>parse解析Configuration类

/p>

p>解析Configuration类

/p>

p>processMemberClasses解析成员嵌套类

/p>

p>processPropertySource处理@PropertySource

/p>

p>componentScanParser.parse处理@ComponentScan

/p>

p>递归解析扫描到的Configuration类.

/p>

p>processImports处理@Import

/p>

p>Process ImportedResource处理@ImportedResource

/p>

p>Proces @Bean methods处理@Bean方法

/p>

p>Process default methods on interfaces解析接口上的@Bean方法

/p>

p>Process superclass, if any寻找父类,递归处理

/p>

p>deferredImportSelectorHandler.process执行延迟ImportSelector

/p>

p>loadBeanDefinitions将所有Bean定义注册到BeanFactory中


循环处理扫描到的所有Configuration类,将Configuration类中定义的Bean,ImportResource的xml文件的Bean,注册Bean到BeanFacotry


Configuration类的顺序按照扫描到的顺序,顺序有以下规则:


a.当前Configuration类ComponentScan扫描扫的Configuration类优先于当前Configuration类。


b.当前Configuration类优先于延时SelectImport的Configuration类(AutoConfiguration类)

/p>

p>registerBeanDefinitionForImportedConfigurationClass

/p>

p>loadBeanDefinitionsForBeanMethod

/p>

p>loadBeanDefinitionsFromImportedResources

/p>

p>loadBeanDefinitionsFromRegistrars

/p>

p>执行BeanDefinitionRegistryPostProcessor::postProcessBeanFactory

/p>

p>按照硬编码,PriorityOrdered注解,Orderd注解,以及剩余的BeanFactoryPostProcessor::postProcessBeanFactory

/p>

p>registerBeanPostProcessors注册拦截Bean创建处理器,会在getBean中创建Bean时调用

/p>

p>顺序注册PriorityOrdered的BeanPostProcessor

/p>

p>顺序注册Ordered的BeanPostProcessor

/p>

p>注册普通的BeanPostProcessor

/p>

p>注册MergedBeanDefinitionPostProcessor

/p>

p>onRefresh扩展点

/p>

p>createWebServer启动WebServer

/p>

p>registerListeners

/p>

p>finishBeanFactoryInitialization实例化ApplicationContext中剩余未实例化的所有Bean

/p>

p>finishRefresh发布事件

/p>

p>ApplicationListener::onApplicationEvent发布ServletWebServerInitializedEvent和ContextRefreshedEvent和DubboApplicationStateEvent

/p>

p>afterRefresh扩展点,在ApplicationContext Refresh完后触发执行

/p>

p>SpringApplicationRunListener::started发布程序已经启动事件

/p>

p>ApplicationListener::onApplicationEvent发布ApplicationStartedEvent和AvailabilityChangeEvent

/p>

p>callRunners扩展点,当程序已经启动后,调用自定义注册的ApplicationRunner和CommandLineRunner,执行运行代码

/p>

p>SpringApplicationRunListener::running发布程序运行事件

/p>

p>ApplicationListener::onApplicationEvent发布ApplicationReadyEvent和AvailabilityChangeEvent

/p>

h3>3.Bean定义加载顺序

/h3>

p>主应用的Bean定义先于AutoConfiguration中的Bean定义加载

/p>

p>主应用扫描的Bean定义之间,没有明确的加载顺序

/p>

p>AutoConfiguration之间可以通过注解定义加载顺序。(注解@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder)

/p>

h2>思考总结

/h2>

p>ConditionalOnMissingBean和ConditionalOnBean


这两个注解只在当前已经扫描加入BeanFacotry的所有Bean中判断某个Bean定义是否存在,所以依赖于Bean定义的扫描加载顺序,不同加载顺序得到判断结果完全不同。


基于上面所说的Bean定义加载顺序,有几下实践建议:

/p>

p>不能在主应用的代码中使用注解,首先AutoConfiguration还没加载(判断AutoConfiguration中的Bean必定是不存在),此时用注解判断AutoCnofiguration定义的Bean没有意义。其次如果用于判断主应用中的Bean定义是否存在,由于主应用Bean加载顺序不确定,代码和xml配置文件修改会导致Bean扫描加载顺序变动引发问题,存在风险不确定性。最重要的是,主应用代码是由当前开发团队编写,代码已经确定Bean存在不存在,不需要在用这两个注解判断,注解反而给后续的人阅读代码引起误解,存在代码不清晰和不确定性。(代码编写追求的特点之一是清晰性。)

/p>

p>在AutoConfiguration中使用这两个注解,如果要判断主应用中是否有定义Bean那么没问题。如果是判断其他AutoConfiguration是否有Bean,那么要用注解确定AutoConfiguration的顺序。最常见稳妥的使用场景,是进行兜底默认配置,判断主应用有没有Bean,如果没有,那么AutoConfiguration进行兜底创建Bean定义。

/p>

p>异步线程调用Dubbo Service服务引发Bean加载死锁


Spring加载Bean会加锁。主线程加载Bean时,如果此时有异步线程进行Dubbo调用,或者加载Bean,会导致两个线程死锁。


比如,在@PostConstruct中启动异步线程调用Dubbo服务初始化缓存。


所以,如果是服务运行必要的初始化内容,一定要预先初始化的,必须在Spring初始化线程中同步执行。


如果要异步初始化,则要在Spring启动完成后再进行,比如订阅ApplicationStartedEvent事件再执行。


保证同时只有一个线程在进行Spring加载Bean。

/p>

h2>最后

/h2>

p>要熟悉SpringBoot启动流程,以及各种配置在启动中的先后顺序,才能在开发中得心应手,避免踩坑。

/p>

编程小号
上一篇 2025-09-20 16:33
下一篇 2025-02-07 16:06

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/hz/141643.html