Spring Boot作为目前最常用的项目配置框架,其自动配置原理可以说是精髓所在。Spring Boot自动配置的原理一般只在面试中会被问到,但作为一名框架使用者,对这种工具的原理有深入理解也是很有必要的。
Spring Boot最主要的作用就是帮我们快速构建庞大的Spring项目,并且尽可能地减少一切xml配置,让我们更关注业务而非配置,即习惯优于配置。
我们知道,使用Spring Boot的项目中有一个全局配置文件:application.properties或application.yml。
我们的各种属性都可以在这个配置文件中配置,比如:server.port、spring.application.*等。
我们会写配置文件,并且也知道配置文件中每个配置的含义,但Spring Boot是如何使这些配置生效的呢?
首先,在Spring Boot的启动类上有一个@SpringBootApplication注解,该注解便是启动自动配置的入口。
@SpringBootApplication是一个复合注解,先看一下其包含的内容:
其中有三个比较重要的注解,接下来分析一下。
跟进这个注解,看其中的内容:
通过这段我们可以看出,在这个注解上面,又有一个 @Configuration 注解。通过上面的注释阅读我们知道:这个注解的作用就是声明当前类是一个配置类,然后Spring会自动扫描到添加了 @Configuration 的类,并且读取其中的配置信息。而 @SpringBootConfiguration 是来声明当前类是SpringBoot应用的配置类,项目中只能有一个。所以一般我们无需自己添加。
关于这个注解,官网上有一段描述:
The second class-level annotation is @EnableAutoConfiguration . This annotation tells Spring Boot to
“guess” how you want to configure Spring, based on the jar dependencies that you have added. Since
spring-boot-starter-web added Tomcat and Spring MVC, the auto-configuration assumes that you are
developing a web application and sets up Spring accordingly.
翻译如下:
第二级的注解 @EnableAutoConfiguration ,告诉SpringBoot基于你所添加的依赖,去“猜测”你想要如何配置
Spring。比如我们引入了 spring-boot-starter-web ,而这个启动器中帮我们添加了 tomcat 、 SpringMVC 的
依赖。此时自动配置就知道你是要开发一个web应用,所以就帮你完成了web及SpringMVC的默认配置了!
可见,@EnableAutoConfiguration便是自动配置的关键所在。SpringBoot内部对大量的第三方库或Spring内部库进行了默认配置,这些配置是否生效,取决于我们是否引入了对应库所需的依赖,如果有那么Spring Boot就会自动配置该jar包。
至于@EnableAutoConfiguration是怎么告诉启动类对依赖进行自动配置的,我们需要进一步对该注解进行探究:
该注解的关键功能由@Import提供,其导入的AutoConfigurationImportSelector 的 getCandidateConfigurations()方法通过SpringFactoriesLoader.loadFactoryNames()扫描所有jar包的META-INF/spring.factories:
最后返回的result实际上就是META-INF/spring.factories对应的Map数据结构。在这个Map中实际上保存了整个Spring中的各个配置类的全类名,包括一些Listener、Filter等等。加载一个类的第一步,就是要获取到对应类的全类名,而之后具体的加载过程实际上是由SpringApplication具体完成的,这里不做先仔细介绍,我们回到我们的重点上,如何自动加载配置。在的spring.factories中,我们来看下边的内容:
在Auto Configure中,SpringBoot会加载全部可能用到的配置类,这些自动配置类都是以 AutoConfiguration结尾来命名的,它实际上就是一个Spring容器配置类。挑一个我们经常用的类ServletWebServerFactoryAutoConfiguration:
在这个类上有一个@EnableConfigurationProperties注解:开启配置属性,而它后面的参数是一个ServerProperties类,这就是习惯优于配置的最终落脚点。
在这个类上,我们看到了一个非常熟悉的注解:@ConfigurationProperties,它的作用就是从配置文件中绑定属性到对应的bean上,而@EnableConfigurationProperties负责导入这个已经绑定了属性的bean到spring容器中。
至此,我们大致可以了解。在全局配置文件中的属性如:server.port等,通过@ConfigurationProperties注解,绑定到对应的XxxxProperties配置实体类上封装为一个bean,然后再通过@EnableConfigurationProperties注解导入到Spring容器中。
如果遇到面试官问到自动配置原理,我们可以这样简短回答:
1. 通过@SpringBootApplication注解下的@EnableAutoConfiguration注解开启自动配置。
2. 该注解会扫描所有jar包的 spring.factories文件,加载文件中对应的自动配置类。
3. 自动配置类通过@ConfigurationProperties注解,将配置文件中的属性绑定到bean上,并注入到spring容器中。