SpringBoot自动配置原理

SpringBoot自动配置原理

Scroll Down

引言

SpringBoot自动配置是SpringBoot当中的精髓,作为精髓,自动配置原理的工作过程往往只有在面试的时候才能用的上,但是如果在工作中你能够深入的理解SpringBoot的自动配置原理,将无往不利。

@EnableAutoConfiguration

@SpringBootApplication注解中

image.png
可以看到@SpringBootApplication中还有@EnableAutoConfiguration注解,这个注解就是用来开启自动配置功能的
image.png
可以看到@EnableAutoConfiguration注解中有@Import(AutoConfigurationImportSelector.class)选择器来导入组件,这个AutoConfigurationImportSelector选择器的作用就是给容器中导入一些组件,该类下面有一个selectImports方法,查看了这个方法里面的代码内容就能知道导入了哪些组件了。
image.png
该方法调用了getAutoConfigurationEntry方法,而getAutoConfigurationEntry方法会返回
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
image.png,这个configurations是用来获取候选的配置,调用的方法有SpringFactoriesLoader.loadFactoryNames()
image.png
然后查看这个SpringFactoriesLoader.loadFactoryNames方法,查看loadFactoryName方法中返回的loadSpringFactories方法
image.png

标注的那个常量就是类路径META-INF/spring.factories

可以知道这个方法是从类路径下得到一个资源,那么得到哪些资源呢?
这个方法的作用是:扫描所有jar包类路径下 META-INF/spring.factories,然后把扫描到的这些文件的内容包装成properties对象。
而这个loadFactoryNames方法传入的factoryType参数,是通过getSpringFactoriesLoaderFactoryClass()这个方法得到的,查看这个方法,发现这个方法返回的是EnableAutoConfiguration.class

image.png

image.png

就是将类路径下META-INF/spring-factories里面配置的所有EnableAutoConfiguration的值加入到了容器中;
image.png

每一个这样的xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;

每一个自动配置类进行自动配置功能

HttpEncodingAutoConfiguratio为例,解释自动配置原理

image.png

@Configuration(proxyBeanMethods = false)   //表示这是一个配置类,也可以给容器中添加组件
@EnableConfigurationProperties(HttpProperties.class)   //启用指定类的ConfigurationProperties功能;将配置文件中对应值和HttpProperties绑定起来,并把HttpProperties加入到IOC容器中
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)  //@Spring底层有@Conditional注解,根据不同的条件,如果满足指定条件,整个配置类里面的配置才会生效,@ConditionalOnWebApplication就是判断当前应用是否是web应用,如果是,生效
@ConditionalOnClass(CharacterEncodingFilter.class)  //判断当前项目有没有CharacterEncodingFilter该类;CharacterEncodingFilter:SpringMVC中进行乱码的过滤器
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)   //判断配置文件中是否存在某个配置(spring.http.encoding:enabled;),matchIfMissing = true如果不存在,判断仍然成立
public class HttpEncodingAutoConfiguration {
	//它已经和SpringBoot的配置文件映射了
	private final HttpProperties.Encoding properties;
	//只有一个有参构造的情况下,参数的值就会从容器中获取
	public HttpEncodingAutoConfiguration(HttpProperties properties) {
		this.properties = properties.getEncoding();
	}

	@Bean  //给容器中添加一个组件,这个组件中的某些值需要从properties中获取
	@ConditionalOnMissingBean
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
		return filter;
	}

根据当前不同条案件判断,决定这个配置类是否生效,一旦生效,这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的

所有在配置文件中能配置的属性都是在xxxProperties类中封装,配置文件能配置什么就可以参照某个功能对应的这个属性类

@ConfigurationProperties(prefix = "spring.http") //从配置文件中获取指定的值和bean的属性进行绑定
public class HttpProperties {

	/**
	 * Whether logging of (potentially sensitive) request details at DEBUG and TRACE level
	 * is allowed.
	 */
	private boolean logRequestDetails;

我们能配置的属性都是来源于这个功能的properties类中

总结

这个@EnableAutoConfiguration注解通过@SpringBootApplication被间接的标记在了Spring Boot的启动类上。在SpringApplication.run(...)的内部就会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有自动配置类加载到Spring容器中。
1.SpringBoot启动时会加载大量的自动配置类;

2.我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;

3.我们再来看这个自动配置类中到底配置了哪些组件(只要我们要用的组组件有,我们就不需要再来配置,若没有,我们可能就要考虑自己写一个配置类让SpringBoot扫描了);

4.给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件汇总指定这些属性的值;

xxxxAutoConfigurartion 自动配置类的作用就是给容器中添加组件

xxxxProperties 的作用就是封装配置文件中相关属性

至此,总算弄明白了 SpringBoot 的自动配置原理。我水平有限,如有不当之处,敬请指出,相互交流学习,希望对你们有帮助。