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方法返回类名集合,方法调用方得到这些集合后,再通过反射获取这些类的类对象、构造方法,最终生成实例。