SpringBoot之AutoConfiguration自动配置原理

SpringBoot自动配置原理

1. 原理

我们在写启动类的时候会用到SpringBootApplication注解,SpringBoot启动的时候加载主配置类,这个注解里面开启了自动配置功能 @EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

   String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

@EnableAutoConfiguration注解的作用是利用AutoConfigurationImportSelector给容器中导入一些组件

看下AutoConfigurationImportSelector这个类里面的selectImports方法 ,这个方法会自动导入很多自动配置类

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
				annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

在这里插入图片描述

自己可以看下PATH路径下的文件

org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration=
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration.AutoConfigureAfter=org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration.ConditionalOnClass=com.datastax.driver.core.Cluster,reactor.core.publisher.Flux,org.springframework.data.cassandra.core.ReactiveCassandraTemplate
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration.ConditionalOnClass=org.apache.solr.client.solrj.SolrClient,org.springframework.data.solr.repository.SolrRepository
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration.ConditionalOnWebApplication=SERVLET
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration=
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration.AutoConfigureBefore=org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.jms.artemis.ArtemisXAConnectionFactoryConfiguration=
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration.ConditionalOnWebApplication=REACTIVE
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration.ConditionalOnWebApplication=REACTIVE
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration=
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration.ConditionalOnWebApplication=SERVLET
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration.ConditionalOnWebApplication=SERVLET
#省略很多

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

例如 我们选择DispatcherServletAutoConfiguration来看下

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)//自动配置优先级 
@Configuration(proxyBeanMethods = false)//表示这是一个配置类
@ConditionalOnWebApplication(type = Type.SERVLET)//Spring底层@Condition注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效;这个注解是判断当前应用是否是web应用,如果是且是servlet类型的,当前配置生效
@ConditionalOnClass(DispatcherServlet.class)//判断当前项目中有没有这个类
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
    
		@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
		public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties webMvcProperties) {
			DispatcherServlet dispatcherServlet = new DispatcherServlet();
			dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
			dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
			dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
			dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
			dispatcherServlet.setEnableLoggingRequestDetails(httpProperties.isLogRequestDetails());
			return dispatcherServlet;
		}

条件满足的情况下这个类的dispatcherServlet方法会给Spring容器初始化一个dispatcherServlet,这个dispatcherServlet的配置是从HttpProperties获取的,看下HttpProperties类

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

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

看下@ConfigurationProperties注解中的spring.http,我们在application.properties中配置的spring.http就会加载进来。

所以精髓来了:

  1. SpringBoot启动会加载大量的自动配置类,这些类在spring-autoconfigure-metadata.properties中有定义
  2. 看我们需要的功能有没有SpringBoot默认写好的自动配置类
  3. 再看这个自动配置类中帮我们配置了哪些组件(只要有我们要用的组件,我们就不需要再配置)
  4. 给容器中自动配置类添加组件的时候,会从xxxProperties类中获取某些属性,我们就可以再配置文件中指定这些属性的值

xxxAutoConfiguration:自动配置类,给容器中添加组件

XXXProperties:封装配置文件中相关属性

2. 细节

  1. 虽然容器启动的时候自动加载了很多自动配置类,但是这些自动配置类大多都是再特定条件满足的情况下才会器作用,主要是@xxxCondition注解在起作用,如果不满足这个Condition那么是不会启动这个类的自动配置的。
    综上所述,自动配置类在一定条件下才能生效
  2. 我们可以启用debug模式,让控制台打印自动配置报告,哪些自动配置生效(positive matches),哪些没有生效(negative matches)
spring.profiles=dev
debug=true
============================
CONDITIONS EVALUATION REPORT
============================


Positive matches:
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

Negative matches:
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)
原创文章 43 获赞 6 访问量 767

猜你喜欢

转载自blog.csdn.net/qq_34088913/article/details/106162067