SpringBoot的运行原理之自动配置

SpringBoot的核心就是自动配置,自动配置又是基于条件判断来配置Bean。关于自动配置的源码在spring-boot-autoconfigure-2.0.3.RELEASE.jar,在这里看:
这里写图片描述

这里写图片描述


查看配置报告
在配置文件中加入如下配置,查看当前已开启和未开启的自动配置报告:

#查看当前项目中已启用和未启用的自动配置的报告
debug: true

启动项目

已开启的配置:
这里写图片描述
未开启的配置:
这里写图片描述


SpringBoot运行原理
先看@SpringBootApplication

  • @SpringBootConfiguration:标记当前类为配置类
  • @EnableAutoConfiguration:开启自动配置
  • @ComponentScan:扫描主类所在的同级包以及下级包里的Bean

关键是**@EnableAutoConfiguration**

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
	Class<?>[] exclude() default {};
	String[] excludeName() default {};
}

关键是@Import(AutoConfigurationImportSelector.class)导入的配置功能,
AutoConfigurationImportSelector中的方法getCandidateConfigurations,得到待配置的class的类名集合

/**
	 * Return the auto-configuration class names that should be considered. By default
	 * this method will load candidates using {@link SpringFactoriesLoader} with
	 * {@link #getSpringFactoriesLoaderFactoryClass()}.
	 * @param metadata the source metadata
	 * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
	 * attributes}
	 * @return a list of candidate configurations
	 */
	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

通过SpringFactoriesLoader.loadFactoryNames()方法扫描META-INF/spring.factories文件
这里写图片描述
这文件列出了哪些需要自动配置。
随便打开一个配置类,例如:
这里写图片描述
都能看到各种各样的条件判断注解,满足条件时就加载这个Bean。
此类的条件注解是:@ConditionalOnProperty

  • @ConditionalOnBean:当容器里有指定Bean的条件下
  • @ConditionalOnClass:当类路径下有指定的类的条件下
  • @ConditionalOnExpression:基于SpEL表达式作为判断条件
  • @ConditionalOnJava:基于JVM版本作为判断条件
  • @ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
  • @ConditionalOnMissingBean:当容器里没有指定Bean的情况下
  • @ConditionalOnMissingClass:当容器里没有指定类的情况下
  • @ConditionalOnWebApplication:当前项目时Web项目的条件下
  • @ConditionalOnNotWebApplication:当前项目不是Web项目的条件下
  • @ConditionalOnProperty:指定的属性是否有指定的值
  • @ConditionalOnResource:类路径是否有指定的值
  • @ConditionalOnOnSingleCandidate:当指定Bean在容器中只有一个,或者有多个但是指定首选的Bean

这些注解都组合了@Conditional注解,只是使用了不同的条件。


通过实例,http编码的默认配置来讲解配置流程
双击shift搜索HttpEncodingProperties,这个类型安全的参数绑定的类就为自动配置http默认编码时提供配置参数。

@ConfigurationProperties(prefix = "spring.http.encoding")
public class HttpEncodingProperties {

	public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

	/**
	 * Charset of HTTP requests and responses. Added to the "Content-Type" header if not
	 * set explicitly.
	 */
	private Charset charset = DEFAULT_CHARSET;//默认编码方式UTF-8

	/**
	 * Whether to force the encoding to the configured charset on HTTP requests and
	 * responses.
	 */
	private Boolean force;

	/**
	 * Whether to force the encoding to the configured charset on HTTP requests. Defaults
	 * to true when "force" has not been specified.
	 */
	private Boolean forceRequest;

	/**
	 * Whether to force the encoding to the configured charset on HTTP responses.
	 */
	private Boolean forceResponse;

	/**
	 * Locale in which to encode mapping.
	 */
	private Map<Locale, Charset> mapping;
	省略set/get
}
  • @ConfigurationProperties(prefix = “spring.http.encoding”):application配置文件配置时前缀是"spring.http.encoding"

双击shift搜索HttpEncodingAutoConfiguration http编码自动配置类,只截取部分代码

package org.springframework.boot.autoconfigure.web.servlet;

@Configuration
@EnableConfigurationProperties(HttpEncodingProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

	private final HttpEncodingProperties properties;

	public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
		this.properties = properties;
	}
	@Bean//设置Bean   CharacterEncodingFilter 
	@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;
	}
}
  • @Configuration:标明为配置类
  • @EnableConfigurationProperties(HttpEncodingProperties.class)声明开启属性注入
  • @ConditionalOnClass(CharacterEncodingFilter.class)当CharacterEncodingFilter在类路径的条件下
  • @ConditionalOnProperty(prefix = “spring.http.encoding”, value = “enabled”, matchIfMissing = true)当spring.http.encoding=enabled的情况下,如果没有设置则默认为true,即条件符合
  • @ConditionalOnMissingBean当容器中没有这个Bean时新建Bean

SpringBoot的核心,自动配置的流程大概就是这个样子,下一篇演示创建自己的starter pom。
SpringBoot核心自动配置之创建自己的starter pom maven依赖包


这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值