SpringBoot 自动配置原理(超级无敌详细)-1

2.自动配置的实现

刚刚我们整体的过了一下主配置文件是如何实现的,但我们还没深入的研究如何实现自动装配功能。我们回到这个文件下,找一个具体的自动配置类进行分析。

jar:file:/apache-maven-3.6.3-repository/org/springframework/boot/spring-boot-autoconfigure/2.2.6.RELEASE/spring-boot-autoconfigure-2.2.6.RELEASE.jar!/META-INF/spring.factories

在这里,我们用 HttpEncodingAutoConfiguration (Http编码自动配置) 作为例子吧

org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\

注释

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {private final HttpProperties.Encoding properties;public HttpEncodingAutoConfiguration(HttpProperties properties) {this.properties = properties.getEncoding();}@Bean@ConditionalOnMissingBeanpublic 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;}@Beanpublic LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {return new LocaleCharsetMappingsCustomizer(this.properties);}private static class LocaleCharsetMappingsCustomizerimplements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {private final HttpProperties.Encoding properties;LocaleCharsetMappingsCustomizer(HttpProperties.Encoding properties) {this.properties = properties;}@Overridepublic void customize(ConfigurableServletWebServerFactory factory) {if (this.properties.getMapping() != null) {factory.setLocaleCharsetMappings(this.properties.getMapping());}}@Overridepublic int getOrder() {return 0;}}}

HttpEncodingAutoConfiguration 的源码分析

1.条件判断

  • 第1行的 @Configuration(proxyBeanMethods = false)

    • //表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
  • 第2行的@EnableConfigurationProperties(HttpEncodingProperties.class)

    • //启动指定类的ConfigurationProperties功能;即自动为HttpEncodingProperties与配置文件中的值进行映射,并加入到IoC容器中

    • 进入HttpProperties.class 类的内部

      @ConfigurationProperties(prefix = "spring.http")
      public class HttpProperties {/*** Whether logging of (potentially sensitive) request details at DEBUG and TRACE level* is allowed.*/private boolean logRequestDetails;/*** HTTP encoding properties.*/private final Encoding encoding = new Encoding();
      
    • 配置文件以spring.http为前缀的值HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中

  • 第3行@ConditionalOnWebApplication

    • //Spring底层@Conditional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效; 判断当前应用是否是web应用,如果是,当前配置类生效
  • 第4行@ConditionalOnClass(CharacterEncodingFilter.class) // 判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;如果存在,当前配置类生效

  • 第5行 @ConditionalOnProperty(prefix = “spring.http.encoding”, value = “enabled”, matchIfMissing = true) //判断配置文件中是否存在某个配置 spring.http.encoding.enabled; matchIfMissing = true的意思是:如果不存在,判断也是成立;即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;


2.获取组件

根据当前不同的条件判断,决定这个配置类是否生效?

**一但这个配置类生效(也就是上面的 第3-5行生效);**那么就会继续往下执行 到第 14-22行

 @Bean@ConditionalOnMissingBeanpublic 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;}

在这里我们可以看见有一个 @Bean ,这个注解的作用就是帮助我们自动的为IoC容器中添加一个 CharacterEncodingFilter 的组件。 添加组件的 时候我们可以注意到 第18行 里,设置setEncoding()的时候需要从 properties 中获取值。 简单的说,添加组件的时候需要用到某些值时,需要到 properties 中获取

3.获取配置文件—properties

properties 又从哪里来?我们可以看到第8行代码中,

private final HttpProperties.Encoding properties;

这一行看起来肯定很眼熟,在前面注解中的第2行代码有出现过这个

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

就是通过配置文件中的值进行对 properties 一一映射。这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;

另外,在第11-13行的时候,我们可以注意到一点,HttpEncodingAutoConfiguration 该自动配置类中 只有一个构造器,那么该构造器需要的参数的值就会自动的从容器中获取。也就是 properties 自动从容器中获取,并传递给 HttpEncodingAutoConfiguration 自动配置类。

 public HttpEncodingAutoConfiguration(HttpProperties properties) {this.properties = properties.getEncoding();}

那既然 properties 中的值已经获取到了,那么就会 回到第18-20行的代码 为过滤器 等这些组件进行赋值,最种实现了自动配置的功能了。

4. 为什么properties配置文件 中可以配置哪些?

不知道发现没,properties 配置文件中的提示是凭空会产生的吗? 其实不是的,这也是有依据的

我们回到第2行@EnableConfigurationProperties(HttpProperties.class),我们可以在properties可以配置什么值是由这个HttpProperties.class决定的,当然了,在不同的自动配置类中,这个也是不一样的。 在 ``HttpProperties这个类的内部,有一个静态内部类Encoding,这个内部类的属性就是我们能够在properties` 能够配置的属性。

public static class Encoding {public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;private Charset charset = DEFAULT_CHARSET;private Boolean force;private Boolean forceRequest;private Boolean forceResponse;private Map<Locale, Charset> mapping;

所以关于 HttpEncodingAutoConfiguration 该自动配置类能够在 properties 配置文件中配置的属性就有这6个啦。

5. @Conditional派生注解(Spring注解版原生的@Conditional作用)

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

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

刚刚我们在看源码的时候,频繁的用到了@Conditional及其拓展注解,其中很重要的一点是,如果不满足指定的条件,那么就不会为容器中添加组件

问题来了,有哪些组件时已经被加入到容器当中了的呢?[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oR6E7Gha-1587629414357)(…/…/AppData/Roaming/Typora/typora-user-images/image-20200423160231043.png)]

笨方法就是一个一个的往自动配置类中查看,哪些时为我们自动配置好了的。不过这好像不太实际,前面我们说到了,SpringBoot可以为了们自动配置 差不多有141个组件, 那我们显然时不能一个一个的查看得了。

这里我们就可以在主配置文件中加入一行

debug=true   //debug模式默认为false

,然后重启SpringBoot,打印日志中就能够为我们显示哪些时已经配置了,那些需要我们自己配置


============================
CONDITIONS EVALUATION REPORT
============================Positive matches:
-----------------AopAutoConfiguration matched:- @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)AopAutoConfiguration.ClassProxyingConfiguration matched:- @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)- @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)Negative matches:
-----------------ActiveMQAutoConfiguration:Did not match:- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)AopAutoConfiguration.AspectJAutoProxyingConfiguration:Did not match:- @ConditionalOnClass did not find required class 'org.aspectj.weaver.Advice' (OnClassCondition)

精髓:

1)、SpringBoot启动会加载大量的自动配置类

2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;

3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)

4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;

SpringBoot 自动配置原理(超级无敌详细)-2相关推荐

  1. 这样讲 SpringBoot 自动配置原理,你应该能明白了吧

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:你在我家门口 juejin.im/post/5ce5effb ...

  2. SpringBoot | 自动配置原理

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 这个月过去两天了,这篇文章才跟大家见面,最近比较累,大家见谅下.下班后闲着无聊看了下 SpringBoot 中的自动配置,把我 ...

  3. 【详解】面试必问:SpringBoot自动配置原理

    前言 SpringBoot框架是开发中的一大利器,其简化了spring的xml的配置,遵循了"约定大于配置"的原则,使用注解对常用的配置做默认配置,减少使用xml配置模式.Spri ...

  4. SpringBoot 自动配置原理

    创建项目 通过Spring Initialize创建SpringBoot项目 而接下来要说的是关于配置文件的事情.关乎配置文件可以参考官方文档. 对于配置文件来说到底在配置文件里面可以进行配置那些内容 ...

  5. SpringBoot实战之SpringBoot自动配置原理

    www.cnblogs.com/leihuazhe/p- SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConf ...

  6. springboot自动配置的原理_SpringBoot实战:详解SpringBoot自动配置原理

    SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...

  7. springboot自动配置原理_今日份学习之Spring Boot自动配置实现原理

    通过前面章节的学习,我们掌握了使用Spring Boot框架进行实际应用开发的方法.在使用Spring Boot 的过程中,我们时常会为一些看似简单,但实际上蕴藏了强大功能的实现而惊呼,下面就让我们来 ...

  8. springboot自动配置原理

    概述 Springboot的基本认识 对于Spring框架,我们接触得比较多的是Spring mvc,Spring IOC.AOP.DI.而这框架如果在使用过程中,随着项目越来越大,引入的技术越来越多 ...

  9. 笑死,面试官又问我SpringBoot自动配置原理

    面试官:好久没见,甚是想念.今天来聊聊SpringBoot的自动配置吧? 候选者:嗯,SpringBoot的自动配置我觉得是SpringBoot很重要的"特性"了.众所周知,Spr ...

最新文章

  1. python 文案自动生成_Python自动化测试如何自动生成测试用例?
  2. mysql分表方法-----MRG_MyISAM引擎分表法
  3. node.js之stream模块
  4. 图解WildFly8之Servlet容器Undertow剖析
  5. python里pip是什么意思_python使用pip的方法是什么
  6. 【LeetCode】【HOT】39. 组合总和(回溯)
  7. 又一家网贷平台宣布退出:已在美股上市,累积借贷金额近三千亿
  8. mysql 中文 3个字节_mysql 字节问题,中文和数字
  9. 突然有点想和你唠嗑了~
  10. 如何将列表分成大小均匀的块?
  11. win10c盘扩容_三招给你的C盘瘦身
  12. tcp协议一定要有服务器吗,复习TCP协议——看这篇就够了
  13. Android 10 根文件系统和编译系统(十八):Android.bp语法
  14. 整流器的输入滤波电容的选择
  15. PHP 获取客户端ip地址
  16. Java之-MyBatis
  17. 谐波均值滤波matlab,谐波均值滤波器.PPT
  18. SwitchHosts使用详解 (转)
  19. [原创]中国象棋翻翻棋,休闲,对战,娱乐,小游戏,jQuery小游戏,下载即用,代码注释全(附源码)
  20. 北大计算机陈鹏,陈鹏(北大教授)

热门文章

  1. SpringMVC(8)——格式化转换器Formatter
  2. Spring框架概述
  3. 日常所需 - 收藏集 - 掘金
  4. 按键精灵两种方法对大漠进行注册regsvr32
  5. 这可能是目前最方便的网站中英文切换(理论支持所有语言)
  6. 如何用Python代码发一个炫酷的朋友圈
  7. CPLEX+Yalmip的MATLAB环境安装
  8. elementui icon图标大全
  9. 安卓虚拟键盘_像科幻片里那样隔空打字,虚拟键盘会成为未来趋势吗?
  10. python对numpy数组求导_NumPy数组计算——python