SpringBoot是如何实现自动配置的

Spring为我们提供了默认配置机制,从而大大提高了开发效率,让我们脱离了配置文件的苦海。但是很多初学的同学们可能会疑惑,默认配置机制究竟是怎么实现的呢?

配置类

SpringBoot在spring-boot-autoconfigure中提供了大量的配置类,如负责配置并初始化tomcat、jetty等的EmbeddedWebServerFactoryCustomizerAutoConfiguration配置类,自然作为配置类,和我们自己写的配置类一样,这个类中也声明了@Configuration注解。

@Configuration // <1.1>
@ConditionalOnWebApplication // <2.1>
@EnableConfigurationProperties(ServerProperties.class) // <3.1>
public class  EmbeddedWebServerFactoryCustomizerAutoConfiguration {

	/**
	 * Nested configuration if Tomcat is being used.
	 */
	@Configuration // <1.2>
	@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
	public static class TomcatWebServerFactoryCustomizerConfiguration {

		@Bean
		public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(
				Environment environment, ServerProperties serverProperties) {
			// <3.2>
			return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
		}

	}

	/**
	 * Nested configuration if Jetty is being used.
	 */
	@Configuration // <1.3>
	@ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class })
	public static class JettyWebServerFactoryCustomizerConfiguration {

		@Bean
		public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(
				Environment environment, ServerProperties serverProperties) {
			 // <3.3>
			return new JettyWebServerFactoryCustomizer(environment, serverProperties);
		}

	}

	/**
	 * Nested configuration if Undertow is being used.
	 */
	// ... 省略 UndertowWebServerFactoryCustomizerConfiguration 代码

	/**
	 * Nested configuration if Netty is being used.
	 */
	// ... 省略 NettyWebServerFactoryCustomizerConfiguration 代码

}

Springboot是如何知道加载那些自动配置类的呢

在我们通过 SpringApplication#run(Class<?> primarySource, String... args) 方法,启动 Spring Boot 应用的时候,有个非常重要的组件 SpringFactoriesLoader 类,会读取 META-INF 目录下的 spring.factories 文件,获得每个框架定义的需要自动配置的配置类。spring.factories中指明了主流框架所需的自动配置类。然后根据我们在pom引入的starter来加载对应的配置类

条件注解

Spring Boot 的 condition 包下,提供了大量的条件注解,通过对条件注解的应用使得我们可以只在满足响应条件的情况下使得某些配置生效。
如代码中<1.2>@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })便声明了需要有 tomcat-embed-core 依赖提供的 Tomcat、UpgradeProtocol 依赖类,才能创建内嵌的 Tomcat 服务器。

配置属性(使我们的配置文件生效)

SpringBoot提供了@ConfigurationProperties注解用于声明配置属性类,不同的前缀(即不同的组件)配置项会有不同的配置属性类,然后如上文代码<3.1>@EnableConfigurationProperties(ServerProperties.class)使得配置属性类生效,也就是说通过将我们的配置文件映射到对应的配置属性类,再讲配置属性类传入到对应的配置类,从而使得我们可以自定义配置。如下为server前缀配置项(tomcat)的配置属性类。

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties
		implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {

	/**
	 * Server HTTP port.
	 */
	private Integer port;

	/**
	 * Context path of the application.
	 */
	private String contextPath;
	
	// ... 省略其它属性
	
}

参考资料

芋道 Spring Boot 自动配置原理