来学习SpringBoot启动器原理,我们先从这两个方面来入手:
1、注解:@SpringBootApplication
2、run方法:SpringApplication.run()
在创建SpringBoot应用时,我们都会写这两个东西,我们来仔细看一下它到底是什么
一、注解:@SpringBootApplication
我们可以发现,SpringBootApplication就是一个接口,在这个接口的上面有几个元注解,需特别注意的是这几个注解:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
我们点进入第一个注解:@SpringBootConfiguration
发现@Configuration注解,所以这是一个配置类,这就想起了我们当时在学习Spring的时候,配置Spring的bean容器有两种配置方式,一种是javaConfig配置类,另外一种就是xml文件来配置,而这里就是声明了一个配置类,然后Spring会自动扫描到添加了`@Configuration`的类,并且读取其中的配置信息。而`@SpringBootConfiguration`是来声明当前类是SpringBoot应用的配置类,项目中只能有一个。所以一般我们无需自己添加。
我们点进入第二个注解:@EnableAutoConfiguration
我们来看看注释是怎么描述的?
开启自动配置的开关,尝试着去猜测你可能需要的bean,这个注解可以去检测classpath下面你定义的bean或者你引入了什么依赖
我们点进入第三个注解:@ComponentScan
点进去后我们发现,好像也就是这样,没有啥,我们再来看看它的注释
大概意思就是:这个配置是扫描哪些配置类的,或者扫描那些以XML形式Spring的bean元素(难道没有想起来当时做SSM时Spring的配置文件中的`<context:component-scan>标签,对,差不多就是这样的)
通过basePackageClasses或者basePackages属性来指定要扫描的包。如果没有指定这些属性,那么将从声明这个注解的类所在的包开始,扫描包及子包
而我们的@SpringBootApplication注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子包。因此,一般启动类会放在一个比较前的包目录中。
二、run方法:SpringApplication.run()
点进去之后,我们在SpringApplication这个类下面发现,把当前的主类当做参数传递下去,并且又new了一个SpringApplication
点进去这个SpringApplication的构造函数之后:
我们再点进去this:
我们可以看到,首先定义了一个资源类加载器resourceLoader、然后把该类放在了一个集合里,判断当前应用的类型
我们查看上幅图的下半部分的那个函数:
判断你的应用是不是包含这些依赖,如果类型和这些都相同,那么你的类型就是WebApplicationType.REACTIVE响应式编程类型
如果不是就会判断的应用是不是Web类型?
如果是Web类型,那么就会返回你的Web类型
接下来
setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));
获取Spring的工厂实例,我们点进入:
这个方法代码大体意思:
获取了当前类的类加载器,然后加载工厂的名字,并把名字放到set集合里,随后通过传入的names,以反射的方式来创建实例
我们先来看,它获取了哪些类的名字,也就是我们看看loadFactoryNames里面到底有什么?
点入:loadSpringFactories方法中:
我们可以看到它是通过类加载器来加载,分为对象加载和静态方法加载。我们看看它加载的是什么?
我们发现classpath下面并没有这个文件目录,所以我们可以去找jar,所以在依赖的jar包下面找到了
我们就来看看这个Spring.factories到底是什么?
原来这个文件里都是需要的一些接口或者类,他们的共同就是都有autoConfiguration
比如我们来看看WebMvcAutoConfiguration
根据@Conditional注解来判断是否启用了该注解。
如果自己想覆盖一些注解,可以通过在yml文件中直接通过key和value来覆盖