springboot是怎么实现自动配置的?

2023-05-16

一、springboot是对spring框架做的一系列优化,减少了大量繁琐的配置,并提供了内置web服务器,让程序运行更快。

1.springboot起步依赖:简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。

2.自动配置Spring以及第三方功能:

SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml(application.yaml)进行配置。

首先打开spring boot项目在springboot的引导类有一个@SpringBootApplication注解:

@Target({ElementType.TYPE}) //修饰类或接口、枚举
@Retention(RetentionPolicy.RUNTIME)//注解在源码,class文件中存在且运行时可以通过反射机制获取到
@Documented//可以在api文档显示
@Inherited//子类可以继承该注解
@SpringBootConfiguration //配置类
@EnableAutoConfiguration//开启自动装配
@ComponentScan //扫描 (不指明包名则默认范围自己所在包及其子类下)
(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

除了基本的元注解外,还有两个。其中:@@SpringBootConfiguration的里面核心是

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration//spring的配置类
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

表明启动类其实也是一个配置类。还有一个是@EnableAutoConfiguration,根据名称翻译就是开启自动配置。它里面包含了如下注解:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

可以看到@AutoConfigurationPackage和@Import({AutoConfigurationImportSelector.class})注解加起来就是实现了自动配置的关键。

@import:提供可以显式的从其他地方加载配置类的方式。有三种方式:

1.普通类

2.接口importSelector的实现类

3.接口importBeanDefintionRegistart的实现类

自动配置就是用来第二种方式。importSelector接口中有一个selectImports方法,返回值是一个字符串数组,数组中的每个元素就是将要被导入的配置类的全限定的类名。

@Import导入了一个AutoConfigurationImportSelector.class的选择器。那么如何根据这个选择器来实现自动配置?

spring框架在底层中使用了springfactories机制,它是Java SPI(SPI(Service Provider Interface),是JDK内置的一种服务提供发现机制,可以用来启用框架扩展和替换组件,主要是被框架的开发人员使用,比如java.sql.Driver接口,其他不同厂商可以针对同一接口做出不同的实现,MySQL和PostgreSQL都有不同的实现提供给用户,而Java的SPI机制可以为某个接口寻找服务实现。Java中SPI机制主要思想是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要,其核心思想就是解耦)的延续,可以借助它来实现自动配置的功能。他的核心逻辑是从Classpath中读取到Jar包中的配置文件META-IF/spring.factories,然后根据知道的key从配置文件中解析出对应的value值。 

回到正题:在AutoConfigurationImportSelector.class中有selectImports方法里面调用了getAutoConfigurationEntry(annotationMetadata)方法,它是自动配置的入口。

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);//自动配置的入口
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

源码如下:

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            //1.获取annotationMetadata的注解@EnableAutoConfiguration的属性
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//2.从资源文件中spring.factories中获取EnableAutoConfiguration对应的所有类
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            //3.通过在注解@EnableAutoConfiguration设置exclude的相关属性,可以指定排除的自动配置类
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            //4.根据@Conditional(满足条件是触发)来判断是否排除某些自动配置类
            configurations = this.getConfigurationClassFilter().filter(configurations);
            //5.触发AutoConfiguration导入相关的事件
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

 核心是第2步:拿到所有全限定类名

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//从spring.factorie找出所有的类
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

总结下流程:从selectimports方法开始:

1.通过ClassLoader去获取classpath中的配置文件spring.factories

 

2.在spring.factories文件里,筛选出以EnableAutoConfiguration为key的配置类(

 3.再根据@Conditional过滤掉不必要的自动配置类

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springboot是怎么实现自动配置的? 的相关文章

随机推荐

  • 配置本地yum源仓库

    配置本地yum源仓库 mount dev cdrom mnt 把光盘挂在到mnt目录下 xff0c xff0c xff0c 因为制作本地yum仓库 xff0c 其目的是需要 rpm文件 xff0c 但是不借助网络 xff0c 本地只有iso
  • MySQL完全备份与恢复

    文章目录 MySQL完全备份与恢复数据备份的重要性数据库备份的分类从物理和逻辑角度分1 物理备份2 逻辑备份 从数据库的备份策略角度 xff0c 备份可分为常见的备份方法MySQL完全备份 优点 缺点 差异备份增量备份 备份方式的比较数据库
  • 成长记录-开启我的新生 (2016-12-06)

    真的是很惊险 xff0c 我差一点就错过了 获得新生 的机会 xff0c 我在蜻蜓音频中听到了逻辑思维 xff0c 从逻辑思维中了解到了 得到 xff0c 从 得到 中订阅了吴军博士的 硅谷来信 xff0c 却在过去的好几个月里 xff0c
  • Maven搭建Mybatis框架详解

    本章我们主要讲述在Maven管理系统下 xff0c 引入Mybatis框架的流程 xff0c 大致分为四个部分 xff1a 1 Maven的环境配置及其项目创建 2 利用Maven的依赖管理 xff08 坐标定位 xff09 导入Mybat
  • 生产者--消费者问题算法的实现

    一 知识背景 1 xff0e 进程管理 2 xff0e 信号量的有关知识 二 目的 1 xff0e 了解信号量的使用 2 xff0e 加深对信号量机制的理解 三 要求 1 xff0e 理解生产者与消费者问题模型 xff0c 掌握解决该问题的
  • 添加修改数据时前端报400的原因

    1 向后端提交的字段跟数据库中的字段对不上 当我们添加或者修改数据时 xff0c 前端跟后端的字段可能对不上 xff0c 如果没有让前后端的字段名保持一致 xff0c 就会导致数据不能正常添加到数据库 xff0c 因此会报400 2 对于某
  • 数组蛇形排序,优质解决方案

    目录 1 题目要求 xff0c 按照指定的行列号内 xff0c 数组按照蛇形的规律排列 xff0c 1 题目要求 xff0c 按照指定的行列号内 xff0c 数组按照蛇形的规律排列 xff0c 比如 1 2 6 7 3 5 8 13 4 9
  • (经典C语言题)1.输入3个字符串,要求按由小到大的顺序输出

    1 总体思路 字符串的比较可以使用 strcmp 函数 xff0c 返回值 gt 0 表示大于 xff0c 返回值小于 0 表示小于 xff0c 返回追等 于 0 表示相同 其他的比较排序思路与数字的排序交换没有区别 xff0c 逐个进行比
  • 【经典C语言题】输入10个整数,将其中最小的数与第一个数对换, 把最大的数与最后一个数对换,要求是使用三个函数

    1 先用函数输入10个数 xff0c 再调整 xff0c 最后输出 2 整体思路 在进行数值逐个比较的同时找到最小值的空间地址以及最大值的空间地址 xff0c 使用这两个空间 中的数据最终与第一和最后数据进行对换即可 3 上代码 1 先解决
  • (C语言经典题)有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数,

    解题思路 1 2 3 4 5 6 7 8 9 前面都向后移动2的话 8 9 1 2 3 4 5 6 7 可以看出就是8 9 换到前面了 先保存最后一位的值9 xff0c 然后前面的所有数字后移一位 xff0c 再把9放到第一位 接下来就是重
  • git简单使用流程

    通过 git status 查看文件的状态 stage 暂存 commit 提交 history 历史 git本地库 push 推送 pull 拉取 remote 远的 repository 仓库 clone 克隆 上传step 1 git
  • MT8788 Android11 修改默认字体,字体大小和像素密度

    环境 MT8788 Android11 ili9881p hd720 dsi vdo 1 修改默认语言 目录 b device mediateksample tb8788p1 64 bsp vnd tb8788p1 64 bsp mk 内容
  • MT8788 Android11 tp 启动流程

    环境 MT8788 Android11 focaltech touch HD720 5寸tp log信息 分析步骤 一 获取dts信息 和 添加驱动到内核 1 获取dts设备树中配置的信息 2 将tp厂商的驱动文件注册添加到 tpd dri
  • 最新Java电子书

    最新Java电子书 JAVA参考大全 J2SE 5EDITION 世界级程序设计大师作品 Thinking in Java第三版 43 第四版 xff08 中文版 43 习题答案 xff09 Java数据库高级编程宝典 Java核心技术第八
  • 关于mtk配置文件的一些说明

    一 ProjectConfig mk 共三种区别 1 AUTO ADD GLOBAL DEFINE BY NAME类型 xff1a 将它后面的名字 xff0c 定义为宏是没有初始值的 define XXX 2 AUTO ADD GLOBAL
  • 监控平台(windows版本)使用SDK的方式接入摄像头

    一 登录进入监控平台管理端 二 添加设备 1 依次点击左侧菜单栏中业务管理 设备管理 xff0c 进入到设备管理界面 如下图 2 点击设备列表字样下的添加按钮添加设备 如下图 3 在添加设备中按如下方式填写 设备编号 可根据需求自行填写 国
  • 认识HTML

    目录 HTML介绍HTML结构HTML常用标签注释标签标题标签段落标签和换行标签格式化标签图片标签超链接标签表格标签列表标签表单标签form和input标签其他标签 无语义标签 HTML特殊字符 HTML介绍 HTML全称是超文本标记语言
  • spring超全面详解

    spring概述 Spring 是于2003年兴起的一款轻量级的 非侵入式的IOC和AOP的一站式的java开发框架 为简化企业级应用开发而生 1 轻量级 就是指spring核心功能的jar包不大 2 非侵入式 我们的业务代码不需要继承或实
  • 虚拟机怎么从图形界面转到命令行(去掉桌面)

    点击 xff1a ctrl 43 alt 43 F1切换到桌面 点击 xff1a ctrl 43 alt 43 F5切换命令行 xff08 去掉桌面 xff09
  • springboot是怎么实现自动配置的?

    一 springboot是对spring框架做的一系列优化 xff0c 减少了大量繁琐的配置 xff0c 并提供了内置web服务器 xff0c 让程序运行更快 1 springboot起步依赖 xff1a 简单的说 xff0c 起步依赖就是