本篇文章所基于的 spring-boot-starter-parent 版本为2.7.10,欢迎大家批评指正。
1.加载过程
大步骤上分两大步创建SpringApplication
对象,运行SpringApplication
对象的run()
方法。
1.1.创建SpringApplication对象
以SpringApplication.run()
方法为入口开始;
(1) 初始化主要的资源加载类的集合并去重;
(2) SpringApplication
对象调用了getSpringFactoriesInstances()
、setInitializers()
和setListeners()
方法。
getSpringFactoriesInstances()
创建并返回了Spring工厂实例,setInitializers()
设置了应用上下文的实例化器ApplicationContextInitializer
,setListeners()
设置了应用的监听器ApplicationListener
;
ApplicationContextInitializer
是在ConfigurableApplicationContext
刷新之前做预处理操作的;ApplicationListener
配合ApplicationEvent
实现事件机制;
(3) 获取Spring工厂实例,加载工厂名称,从META-INF/spring.factories中读取键值,其中包括key为ApplicationContextInitializer
的键值,这些初始化器将设置为应用的上下文初始化器;
(4) 利用Spring工厂实例创建监听器,并设置监听器
(5) 获得启动类
1.2.执行run方法
(1) 开始计时;
(2) 获取监听器,开启监听;
(3) 加载 java 命令中的参数值;
(4) 准备环境,如profile、property、系统信息,对应代码ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments)
;
(5) 打印banner;
(6) 创建上下文,对应代码context = createApplicationContext()
,此时创建beanFactory。GenericApplicationContext
的构造方法将new一个DefaultListableBeanFactory
,然后我们将看到,在AnnotationConfigApplicationContext
类的无参构造方法中,创建注解Bean定义的读取器,还有classpath中Bean定义的扫描器;
(7) 准备上下文,包括调用初始化器的初始化方法、触发监听器的监听事件、打印日志、获取beanFactory、注册单例、加载资源文件、读取;
扫描和实际创建Bean的单例被分开了。
(8) 刷新容器上下文,这其中有ServletWebServerApplicationContext
类的刷新也有ReactiveWebServerApplicationContext
类的刷新;
(9) 刷新后的步骤;
(10) 计算启动用时;
(11) 启动监听器;
(12) 遍历所有runner,调用run方法。
2.主启动类的注解
我们都知道,对于Spring boot开箱的项目,会用 @SpringBootApplication
这一注解来标记某个类,从而使得这个类成为了主配置类,Spring boot通过运行main方法启动应用。@SpringBootApplication
本质上是诸多注解的集合。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
其中,@Target(ElementType.TYPE)
、@Retention(RetentionPolicy.RUNTIME)
、@Documented
、@Inherited
是Java自带的,不在本文阐述。重点关注下面的@SpringBootConfiguration
、@EnableAutoConfiguration
、@ComponentScan
。
@SpringBootConfiguration
是@Configuration
和@Indexed
的集合,@Configuration
的功能是标注当前的类为配置类,会将类中声明的以@Bean
注解标记的方法的实例置入 Spring 容器中,名称则为对应的方法名;@Indexed
标记的类编译打包的时候会在项目中自动生成META-INT/spring.components文件,以便在@ComponentScan
扫描时可以不扫描指定的包,提升了扫描的速率。
@EnableAutoConfiguration
是@AutoConfigurationPackage
和@Import
的集合。@AutoConfigurationPackage
用来把我们注解所在包路径加入了一个集合里,这个集合保存了一些包路径;@Import
用来将配置类或者需要预先加载的类加载 spring 到容器中。
@ComponentScan
最主要的作用是指定扫描哪些包下的类需要自动装配到 spring 容器中,默认是启动类所在包及其下属所有子包。