Springboot自动配置原理
首先我们先从启动类入手,可以看到有两处值得关注的地方:
- 注解:@SpringBootApplication
- run方法:SpringApplication.run()
一、先看下@SpringBootApplication这个注解
可以看到上面也有很多注解,这里需要重点了解的注解有以下3个:
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
(一)、继续查看源码 @SpringBootConfiguration
这里可以看到,在@SpringBootConfiguration这个注解上,又有一个 @Configuration注解。表明声明当前的类是一个配置类,Spring会自动扫描到添加了@Configuration的类,并且读取其中的配置信息。而@SpringBootConfiguration是用来声明当前类是SpringBoot的应用的配置类,项目中只能有一个,我们不需要手动添加。
(二)、@EnableAutoConfiguration
可以看到这个类上有段说明
大致的意思就是:启用Spring应用程序上下文的自动配置,尝试猜测和配置您可能需要的bean。比如我们引入了spring-boot-starter-web ,而这个启动器中帮我们添加了tomcat 、SpringMVC的依赖。此时自动配置就知道你是要开发一个web应用,所以就帮你完成了web及SpringMVC的默认配置了!
总结:当使用springboot创建项目,只需引入所需框架的依赖,配置就可以交给springboot处理了。(三)、@ComponentScan 注解
查看源码可以看到类上的注释:
- 大致可以理解为:它的作用类似于标签context:component-scan标签的作用,通过basePackageClasses或者basePackages属性指定要扫描的包。如果没有指定这些属性,那么将从声明这个注解的类所在的包开始,扫描包和子包。
- @SpringBootApplication注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子包。所以一般启动类会放在一个比较前的包目录中。
二、默认配置原理
(一)、spring.factories
在SpringApplication类构建的时候,可以看到有这样一段代码
点进去
可以看到,loadFactoryNames加载了一些FactoryName,然后利用createSpringFactoriesInstances将这些加载到的类名进行实例化。
继续点进loadFactoryNames这个方法,可以看到下面有段通过类加载器加载文件的代码:
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
可以看到加载的文件地址是:META-INF/spring.factories。ClassLoader默认是从classpath下读取文件的,所以,springboot会在初始化的时候,加载所有classpath:META-INF/spring.factories文件,包括jar包当中的。而在spring的一个依赖包:spring-boot-autoconfigure中,就有这样的文件
所以以后我们引入任何第三方启动器,只需要实现自动配置,也都会有类似文件。
(二)、默认配置类
打开刚才的spring.factories文件:
可以发现以EnableAutoConfiguration接口为key的一系列配置,key所对应的值,就是所有自动配置类,可以在当前的jar包中找到这些自动配置类:
这里看下springMvc的自动配置类:
我们可以看下WebMvcAutoConfiguration这个类上的几个注解:
- @Configuration:声明这是一个配置类
- @ConditionalOnWebApplication(type =Type.SERVLET):满足项目的类是Type.SERVLET类型,也就是一个普通web工程
- @ConditionalOnClass({Servlet.class,DispatcherServlet.class,WebMvcConfigurer.class}):满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer,其中Servlet只要引入了Tomcat依赖才会有,后两个需要引入SpringMVC才会有。这里就是判断是否引入了相关依赖,引入后条件才会成立,当前配置类才会生效。
- @ConditionalOnMissingBean(WebMvcConfigurationSupport.class):OnMissingBean,说明环境中没有指定的bean才生效。这就是自定义配置的入口。
再看下WebMvcConfigurationSupport这个类:
视图解析器:
处理器适配器(HandlerAdapter):
(三)、默认属性配置
配置的属性从哪来?从下图可以看到,在WebMvcAutoConfiguration中,下面通过注解注入了两个属性:WebMvcProperties.class, ResourceProperties.class
分别查看这两个属性类:
WebMvcProperties中找到了内部资源视图解析器的prefix和suffix后缀
而ResourceProperties中定义了静态资源的路径:
用法:如果我们需要覆盖这些属性,只需要在配置文件application.properties中定义与其前缀prefix和字段名一致的属性即可。
三、总结
(一)、使默认配置生效的步骤
- @EnableAutoConfiguration注解会去寻找META-INF/spring.factories文件,读取其中以EnableAutoConfiguration为key的所有类的名称,这些类是提前写好的自动配置类。
- 这些类都声明了@configuration注解,并且通过@bean注解提前配置了我们需要的一切实例,但是这些配置不一定生效,因为有@ConditionalOn注解,满足一定条件才 会生效。
- 类要存在,我们只需要引入相关依赖,依赖有了条件成立,自动配置生效。
- 如果我们自己配置了相关bean,那么会覆盖默认的自动配置的bean
- 我们还可以通过application.yml文件来覆盖自动配置中的属性。
(二)、启动器
只要引入springboot提供的(stater)启动器,就能自动管理依赖及版本了,所以使用springboot的第一件事就是找启动器。
(三)、全局配置
Springboot的默认配置都会读取默认属性,这些属性可以通过自定义application.properties文件进行覆盖。这样虽然使用的还是默认配置,但是配置中的值已经改成我们自定义的了。
因此,使用springboot的第二件事就是通过配置文件进行覆盖默认的属性值,形成自定义配置。
属性文件支持两种格式:application.yml和application.properties
Yml的语法如下:
jdbc:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springboot_test
username: root
password: root
server:
port: 80
如果两个配置文件都存在且属性重复,则properties优先。
遇到需要修改的组件的配置项流程如下: