SpringBoot启动原理

本文深入解析SpringBoot的启动过程,包括@SpringBootApplication注解的作用,SpringApplication的执行流程,以及自动配置模块的实现机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.SpringBootApplication注解作用
    SpringBootApplication注解是SpringBoot的核心注解,其主要作用等同于@Configuration、@EnableAutoConfiguration、@ComponentScan这三个注解
    (1) @Configuration
        JavaConfig形式的Spring Ioc容器的配置类使用的那个@Configuration,SpringBoot社区推荐使用基于JavaConfig的配置形式,
        所以这里的启动类标注了@Configuration之后,本身其实也是一个IoC容器的配置类。
        将Spring配置文件由XML形式改变为注解形式,原在XML中定义的Bean标签改为代码中通过@Bean注解的形式来修饰方法,返回值为定义的Bean实现类。
    (2) @ComponentScan
        自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。
        可通过BasePackage等属性来细粒度的定制@ComponentScan的扫描范围,如果不指定,则默认会从声明了@ComponentScan所在类的package进行扫描。
        所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages。
    (3) @EnableAutoConfiguration
        借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器中。
        通过@Import(EnableAutoConfigurationImportSelector.class)将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。
        其加载过程通过SpringFactoriesLoader实现。
        [1] SpringFactoriesLoader
            SpringFactoriesLoader属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件META-INF/spring.factories加载配置。
            它更多是提供一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为Key,获取对应的一组@Configuration类。
            从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射实例化为
            对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。
            
2.SpringApplication执行流程
    (1) 如果我们使用的是SpringApplication的静态run方法,那么这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。
        在SpringApplication实例初始化之前会先执行以下几个步骤
        [1] 根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
        [2] 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
        [3] 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
        [4] 推断并设置main方法的定义类。
    (2) SpringApplication实例初始化完成并且完成设置后,开始执行run方法的逻辑,首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener,调用started()方法。
    (3) 创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
    (4) 遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法。
    (5) 如果SpringApplication的showBanner属性被设置为true,则打印banner。
    (6) 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,
        然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,将之前准备好的Environment设置给创建好的ApplicationContext使用。
    (7) ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,
        然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
    (8) 遍历调用所有SpringApplicationRunListener的contextPrepared()方法。
    (9) 将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
    (10)遍历调用所有SpringApplicationRunListener的contextLoaded()方法。
    (11)调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
    (12)查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
    (13)正常情况下,遍历执行SpringApplicationRunListener的finished()方法
    
3.SpringApplication执行流程总结
    (1)收集各种条件和回调接口
    (2)调用SpringApplicationRunListener的started()方法
    (3)创建并准备Environment
    (4)便利调用所有SpringApplicationRunListener的environmentPrepared()的方法。
    (5)创建并初始化ApplicationContext,并设置Environment加载配置等
    (6)遍历调用所有SpringApplicationRunListener的contextPrepared()方法和contextLoaded()方法。
    (7)调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
    (8)执行所有的CommandLineRunner,和所有SpringApplicationRunListener的finished()方法
    
    Springboot的启动主要创建了配置环境(environment)、事件监听(listeners)、应用上下文(applicationContext),并基于以上条件在容器中开始实例化我们需要的Bean,通过SpringBoot启动的程序构造完成
    
4.SpringBoot自动配置模块的实现
     该配置模块的主要使用到了SpringFactoriesLoader,即Spring工厂加载器,该对象提供了loadFactoryNames方法,入参为factoryClass和classLoader,
     即需要传入工厂类名称和对应的类加载器,方法会根据指定的classLoader,加载该类加器搜索路径下的指定文件,即spring.factories文件,
     传入的工厂类为接口,而文件中对应的类则是接口的实现类,或最终作为实现类,所以文件中一般为一对多的类名集合,获取到这些实现类的类名后,
     loadFactoryNames方法返回类名集合,方法调用方得到这些集合后,再通过反射获取这些类的类对象、构造方法,最终生成实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值