您的位置:首页 > 编程语言 > Java开发

SpringBoot之AutoConfiguration自动配置原理

2020-07-21 04:14 1476 查看

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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: