03 Spring Boot 自动配置及原理分析

Spring Boot 自动配置及原理分析

专栏列表

  1. Spring Boot 入门及环境构建
  2. Spring Boot 配置
  3. Spring Boot 自动配置及原理分析
  4. Spring Boot 日志
  5. SpringBoot Web 开发、Thymeleaf 模版 Spring MVC
  6. SpringBoot RESTful风格的增删改查 CRUD

自动配置原理

配置文件到底能写什么?怎么写?自动配置原理;

配置文件能配置的属性参照

SpringBoot启动的时候加载主配置类,开启了自动配置功能

@SpringBootApplication
@EnableAutoConfiguration

@EnableAutoConfiguration 作用

  • 利用EnableAutoConfigurationImportSelector给容器中导入一些组件

  • 可以插件 selectImport() 方法的内容

  • getAutoConfigurationEntry方法中

    // 获取候选的配置
    List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);
    
  • getCandidateConfigurations方法中,SpringFactoriesLoader.loadFactoryNames(),扫描所有jar包类路径下 META-INF/spring.factories,把扫描到的这些文件的内容包装成properties对象,从properties中获取到EnableAutoConfiguration.class(类名)对应的值,然后把它们添加在容器中

    将类路径下 META-INF/spring.factories 里面配置的所有 EnableAutoConfiguration 的值加入到了容器中
    在这里插入图片描述

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

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

以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理

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

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.Encoding;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.filter.CharacterEncodingFilter;

// 表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
@Configuration(proxyBeanMethods = false)

/**
 * 启动指定类的ConfigurationProperties功能;
 * 将配置文件中对应的值和HttpProperties绑定起来;
 * 并把HttpProperties加入到ioc容器中
 */
@EnableConfigurationProperties({HttpProperties.class})
// HttpEncodingProperties

/**
 * Spring底层@Conditional注解
 * 根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效;
 * 判断当前应用是否是web应用,如果是,当前配置类生效
 */
@ConditionalOnWebApplication(
  type = Type.SERVLET
)

//判断当前项目有没有这个类
@ConditionalOnClass({CharacterEncodingFilter.class})

/**
 * 判断配置文件中是否存在某个配置  spring.http.encoding.enabled;如果不存在,判断也是成立的
 * 即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
 */
@ConditionalOnProperty(
  prefix = "spring.http.encoding",
  value = {"enabled"},
  matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
  // 它已经和SpringBoot的配置文件映射了
  private final 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(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
    filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
    return filter;
  }
  
  @Bean
  public HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
    return new HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer(this.properties);
  }
  
  static class LocaleCharsetMappingsCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
    private final Encoding properties;
    
    LocaleCharsetMappingsCustomizer(Encoding properties) {
      this.properties = properties;
    }
    
    public void customize(ConfigurableServletWebServerFactory factory) {
      if (this.properties.getMapping() != null) {
        factory.setLocaleCharsetMappings(this.properties.getMapping());
      }
    }
    
    public int getOrder() {
      return 0;
    }
  }
}
  1. 根据当前不同的条件判断,决定这个配置类是否生效
  2. 一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;

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

@ConfigurationProperties(
  prefix = "spring.http"
)
public class HttpProperties {
  private boolean logRequestDetails;
  private final HttpProperties.Encoding encoding = new HttpProperties.Encoding();
// 从配置文件中获取指定的值和 bean 的属性进行绑定
@ConfigurationProperties(prefix = "spring.http.enncoding")
public class HttpEncodingProperties{
  public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
}

@ConfigurationProperties 执行器配置依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

总结

  • SpringBoot启动会加载大量的自动配置类
  • 我们看我们需要的功能有没有SpringBoot默认写好的自动配置类
  • 再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
  • 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值

xxxxAutoConfigurartion:自动配置类;

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

@Conditional派生注解

作用:必须是 @Conditional 指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

@Conditional扩展注解作用(判断是否满足当前指定条件)
@ConditionalOnJava系统的java版本是否符合要求
@ConditionalOnBean容器中存在指定Bean;
@ConditionalOnMissingBean容器中不存在指定Bean;
@ConditionalOnExpression满足SpEL表达式指定
@ConditionalOnClass系统中有指定的类
@ConditionalOnMissingClass系统中没有指定的类
@ConditionalOnSingleCandidate容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty系统中指定的属性是否有指定的值
@ConditionalOnResource类路径下是否存在指定资源文件
@ConditionalOnWebApplication当前是web环境
@ConditionalOnNotWebApplication当前不是web环境
@ConditionalOnJndiJNDI存在指定项

查看那些自动配置类生效了

自动配置类必须在一定的条件下才能生效;

我们怎么知道哪些自动配置类生效了;

我们可以通过配置文件启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;

  • Positive matches :(自动配置类启用的)
  • Negative matches:(没有启动,没有匹配成功的自动配置类)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin KDA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值