Spring-自动配置
自动配置流程细节梳理:
1、导入starter-web
:导入了web开发场景
- 1、场景启动器导入了相关场景的所有依赖:
starter-json
、starter-tomcat
、springmvc
- 2、每个场景启动器都引入了一个
spring-boot-starter
,核心场景启动器。(上面三个也有) - 3、核心场景启动器引入了
spring-boot-autoconfigure
包。 - 4、
spring-boot-autoconfigure
里面囊括了所有场景的所有配置。 - 5、只要这个包下的所有类都能生效,那么相当于SpringBoot官方写好的整合功能就生效了。
- 6、SpringBoot默认却扫描不到
spring-boot-autoconfigure
下写好的所有配置类。(这些配置类给我们做了整合操作),默认只扫描主程序所在的包。
2、主程序:@SpringBootApplication
- 1、
@SpringBootApplication
由三个注解组成@SpringBootConfiguration
声明配置类、@EnableAutoConfiguratio
、@ComponentScan
扫描指定组件包 - 2、SpringBoot默认只能扫描自己主程序所在的包及其下面的子包,扫描不到
spring-boot-autoconfigure
包中官方写好的配置类 - 3、
@EnableAutoConfiguration
:SpringBoot 开启自动配置的核心。- 1、是由
@Import(AutoConfigurationImportSelector.class)
提供功能:批量给容器中导入组件。 - 2、SpringBoot启动会默认加载 142个配置类。
- 3、这142个配置类来自于
spring-boot-autoconfigure
下META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件指定的
项目启动的时候利用 @Import 批量导入组件机制把autoconfigure
包下的142xxxxAutoConfiguration
类导入进来(自动配置类)命名规范都是以xxxxAutoConfiguration
结尾的自动配置类
虽然导入了142个自动配置类 - 4、按需生效:
并不是这142个自动配置类都能生效
每一个自动配置类,都有条件注解@ConditionalOnxxx
,只有条件成立,才能生效
- 1、是由
3、xxxxAutoConfiguration自动配置类
- 1、给容器中使用@Bean 放一堆组件。
- 2、每个自动配置类都可能有这个注解
@EnableConfigurationProperties(ServerProperties.class)
,用来把配置文件中配的指定前缀的属性值封装到xxxProperties
属性类中 - 3、以Tomcat为例:把服务器的所有配置都是以
server
开头的。配置都封装到了属性类中 - 4、给容器中放的所有组件的一些核心参数,都来自于
xxxProperties
。xxxProperties
都是和配置文件绑定。 - 只需要改配置文件的值,核心组件的底层参数都能修改
核心流程总结:
1、导入starter
,就会导入autoconfigure
包。
2、autoconfigure
包里面 有一个文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
,里面指定的所有启动要加载的自动配置类
3、@EnableAutoConfiguration
会自动的把上面文件里面写的所有自动配置类都导入进来。xxxAutoConfiguration
是有条件注解进行按需加载
4、xxxAutoConfiguration
给容器中导入一堆组件,组件都是从 xxxProperties
中提取属性值
5、xxxProperties
又是和配置文件进行了绑定
效果:导入starter
、修改配置文件,就能修改底层行为。
点开依赖,找到autoconfigure
包
autoconfigure
包里面写了SpringBoot官方的所有场景的全场景的各种配置
比如Web相关的所有配置
JDBC相关的所有配置
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered{
//批量导入组件
@0verride
public String[] selectImports(AnnotationMetadata annotationMetadata){
if(!isEnabled(annotationMetadata)){
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata)
return stringUtils.toStringArray(autoConfiqurationEntry.getConfigurations());
}
SpringBoot加载进来24个配置,这些配置又是从哪来的
可以看到是从getCandidateConfigurations
方法里返回的全类名。
去getCandidateConfigurations
方法看看
可以看到是调用了工具类ImportCandidates
,然后loadAutoconfiguration.class
这个类,configurations
现在默认有140+个配置类,远大于返回的24个配置类。
如果找不到这个配置类,则会报错,沿着提示给的路径去看看文件
可以看到文件里存着140多个全类名,并且都以AutoConfiguration
为结尾。
//以Tomcat为例
//属性绑定,追入ServerProperties.class看看
@AutoConfiguration
@ConditionalOnNotWarDeployment
@ConditionalOnWebApplication
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactorycustomizerAutoconfiquration {
@Configuration(proxyBeanMethods =false)
@ConditionalOnclass({ Tomcat.class, UpgradeProtocol.class })
public static class TomcatWebServerFactoryCustomizerConfiguration {
@Bean
public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment,
ServerProperties serverProperties){
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
}
}
}
//把配置文件中所有以"server"开头的,所以跟ServerProperties 一一对应的属性进行绑定,
//比如server.port;server.address
//属性类把配置文件绑定在类中,而且把这个类放进容器中
//为啥要把属性类放进容器中?
//因为给容器放入Tomcat自定义工厂组件的时候,它要求传入ServerProperties
//而@Bean的方法参数中如果容器里面有,就去容器里拿;而正好我们把属性类放入了容器
@ConfiqurationProperties(prefix="server", iqnoreUnknownFields =true)
public class ServerProperties {
private Integer port;
private InetAddress address;
private String serverHeader;
...
}
自动配置原理2.0--spring-web版
新建一个spring-boot项目,勾选spring-web和lombok
先看依赖接结构,start-web
整合了json
,tomcat
,web
,webmvc
,自动配置的功能主要在starter
里的autoconfigure
(依赖)里面,进去autoconfigure
看看是怎么个事儿
找到包
由于项目启动时只会扫描主程序当前所在的包,上面的包是扫不到的,所以是靠主程序的@SpringBootApplication注解来实现,前面有讲这个注解的组成,由@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan组成。
@ComponentScan
解决扫描包的问题,@EnableAutoConfiguration
解决自动配置问题,那么它是如何把我们需要的类注册进容器中的呢?追进@EnableAutoConfiguration
发现它由@Import({AutoConfigurationImportSelector.class})
构成,这个注解的作用就是批量导入自动配置类。具体是怎么批量导入的呢?追进AutoConfigurationImportSelector.class
,看不懂,不如设个断点调试一下,可以在上面的图看到getAutoConfigurationEntry方法里返回了自动配置类的entry,list里面有24个我们需要的自动配置类的全类名,这些类名又是如何拿到的?追进getCandidateConfigurations方法,发现它是加载了AutoConfiguration.class
这个类,并且后面有个文件路径,这个路径存的就是所有自动配置类的全类名,
随便点进一个关于web的自动配置类看看,发现都有@ConditionalOnClass
注解,意思是当类__存在时,才会加载这个配置类。即实现了按需加载。所以前面的list有24个而非150多个。配置类又会往容器里注册多个组件。组件里的属性都绑定在xxxProperties类中,xxxProperties类又与配置文件绑定,所以修改配置文件就能实现组件属性的修改。