springboot 自动装配原理

一.原理解释

Spring Boot的自动配置是Spring框架的一个重要特性,它旨在简化应用程序的开发和部署过程。自动配置通过基于类路径中的依赖关系和配置文件内容来预先配置Spring应用程序的各种组件和功能。这样,我们可以在无需显式配置大量参数的情况下,快速搭建一个运行良好的Spring应用程序,极大的提高了我们的开发效率。

下面我们对于Spring Boot自动配置的工作原理做一个详细解释(我们只谈原理和概念,不设计实现)
springboot的自动装配使用了很多的技术点,它是在别的基础基础上做了整合,springboot在启动流程的时候,通过加载mata-info/spring.factory文件,加载自动化配置的文件。它使用的主要技术点主要有以下几点

1.Spring Boot Starter :

Spring Boot提供了一系列Starter模块,每个Starter模块都包含了特定功能的默认依赖和配置。例如,spring-boot-starter-web包含了构建Web应用程序所需的依赖和配置。这些Starter模块通过自动配置来简化应用程序的搭建,开发者只需添加相应的Starter依赖,即可自动启用相关功能。

条件装配:

Spring Boot的自动配置采用了条件装配的机制。条件装配根据特定条件来决定是否创建特定的Bean或应用特定的配置。这些条件可以基于类路径中存在的依赖、配置属性的值、环境变量或其他Spring Bean的存在等。这样,当满足特定条件时,相关的Bean会被自动创建和配置,否则它们将被跳过。条件装配主要依赖于条件注解

条件注解:

Spring Boot中有许多条件注解,这些注解用于根据特定条件来启用或禁用配置。例如,@ConditionalOnClass注解表示只有类路径中存在指定的类时,相关配置才会生效。@ConditionalOnProperty注解则允许根据配置属性的值来决定是否启用某个配置。

Spring Boot的启动过程:

当Spring Boot应用程序启动时,会触发自动配置的过程。首先,它会扫描类路径上的所有Starter模块,并加载它们的自动配置类。然后,Spring Boot会根据条件装配机制,检查是否满足自动配置的条件,并决定是否创建相应的Bean和应用相关的配置。

springboot的自动配置

自动配置类的优先级:

在某些情况下,可能存在多个自动配置类都能满足条件的情况。为了解决这种冲突,Spring Boot为自动配置类定义了优先级。具有更高优先级的配置类将覆盖具有较低优先级的配置类。这样,开发者可以通过自定义配置类来覆盖Spring Boot默认的自动配置行为。

自定义自动配置:

Spring Boot允许开发者定义自己的自动配置类。要创建自定义的自动配置,只需在类上添加@Configuration注解,并在类中配置所需的Bean。然后,Spring Boot会在启动过程中将这些自定义配置类纳入自动配置的流程中。

其实总言而之,自动配置就是做了封装,对于我们习惯性的操作全部进行简化!在实现上,Spring Boot的自动配置通过条件装配机制和Starter模块来简化Spring应用程序的开发过程。它根据类路径中的依赖、配置属性的值以及其他条件来决定是否创建特定的Bean和应用相关的配置。这种自动化的特性使得开发者可以更加专注于业务逻辑,而无需过多关注繁琐的Spring配置。

约定大于配置

"约定大于配置"是一种软件开发的设计原则,它强调通过制定一系列约定和默认规则,来降低配置的复杂性,从而简化开发和部署过程。这个原则在很多开发框架和工具中都有应用,其中就包括Spring Boot,既然讲到了自动配置,我们就做一个延伸,对于此概念也做一个解释!

具体来说,"约定大于配置"的理解可以从以下几个方面:

默认约定:

在"约定大于配置"的理念下,开发框架或工具会预定义一些默认约定。这些默认约定规定了开发者在遵循特定命名规则、目录结构或配置属性时将会获得某种预期的行为或功能。通过使用这些默认约定,开发者无需显式配置大量细节,可以快速启动和运行应用程序。

简化配置:

通过遵循约定,很多配置信息可以被自动推断或者从默认值中获取。这样,开发者在进行配置时,只需关注少量的关键配置,而不用逐个配置每个细节,从而简化了配置过程。

提高一致性:

约定大于配置有助于在团队开发中建立一致的代码风格和项目结构。所有团队成员都遵循相同的约定,从而降低了沟通和协作的成本。

降低学习曲线:

使用约定大于配置的框架或工具,开发者无需过多了解复杂的配置选项,只需要学习一些基本的约定即可开始工作。这有助于降低学习曲线,使新手能够更快地上手。

灵活性和扩展性:

尽管约定大于配置提供了默认规则,但它并不意味着开发者完全不能进行自定义配置。框架通常会提供一些扩展点,允许开发者根据自己的需求进行配置和定制。

总体而言,"约定大于配置"是一种设计原则,它通过提供默认约定和简化配置的方式,降低了应用程序开发和部署的复杂性,使开发者能够更加专注于业务逻辑的实现,从而提高开发效率和代码质量。

springboot是如何实现自动配置的

首先我们先来看一些 springboot 的核心注解 @SpringBootApplication 的类:

在这里插入图片描述
点击 @SpringBootConfiguration 注解,发现这个注解其实就是一个配置注解,SpringBoot 把 @Configuration 注解做一个包装。

在这里插入图片描述
在这里插入图片描述
所以说 @SpringBootApplication 是一个复合注解,大概就可以把 @SpringBootApplication 看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。根据 SpringBoot 官网,这三个注解的作用分别是:

  • @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制。
  • @Configuration:允许在上下文中注册额外的 bean 或导入其他配置类,作用与 applicationContext.xml 的功能相同。
  • @ComponentScan: 扫描包下的类中添加了@Component (@Service,@Controller,@Repostory,@RestController)注解的类 ,并添加的到spring的容器中,可以自定义不扫描某些 bean。如下图所示,容器中将排除TypeExcludeFilter和AutoConfigurationExcludeFilter。

在这里插入图片描述
@EnableAutoConfiguration:实现自动装配的核心注解

EnableAutoConfiguration 只是一个简单地注解,自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector 类。

在这里插入图片描述
我们现在重点分析下 AutoConfigurationImportSelector 类到底做了什么?

AutoConfigurationImportSelector:加载自动装配类

AutoConfigurationImportSelector 类的继承体系如下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看出,AutoConfigurationImportSelector 类实现了 ImportSelector 接口,也就实现了这个接口中的 selectImports 方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。

在这里插入图片描述
这里我们需要重点关注一下 getAutoConfigurationEntry方法,这个方法主要负责加载自动配置类的。

该方法调用链如下

在这里插入图片描述
现在我们结合 getAutoConfigurationEntry 方法的源码来详细分析一下:

在这里插入图片描述

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {//第1步:判断自动装配开关是否打开if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}//第2步:用于获取注解中的exclude和excludeName。//获取注解属性AnnotationAttributes attributes = getAttributes(annotationMetadata); //第3步:获取需要自动装配的所有配置类,读取META-INF/spring.factories//读取所有预配置类List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);//第4步:符合条件加载//去掉重复的配置类configurations = removeDuplicates(configurations);//执行Set<String> exclusions = getExclusions(annotationMetadata, attributes);//校验checkExcludedClasses(configurations, exclusions);//删除configurations.removeAll(exclusions);//过滤configurations = getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);//创建自动配置的对象return new AutoConfigurationEntry(configurations, exclusions);
}

第 1 步:判断自动装配开关是否打开。默认 spring.boot.enableautoconfiguration = true,可在 application.properties 或 application.yml 中设置在这里插入图片描述
在这里插入图片描述
第 2 步:用于获取 EnableAutoConfiguration注解中的 exclude 和 excludeName。

在这里插入图片描述
第 3 步

获取需要自动装配的所有配置类,读取META-INF/spring.factories

先进入 getCandidateConfigurations() 方法中:

在这里插入图片描述
进入 loadFactoryNames() 方法中:

在这里插入图片描述
再进入 loadSpringFactories() 方法中:

在这里插入图片描述
在这里插入图片描述
从下图可以看到这个文件的配置内容都被我们读取到了。

在这里插入图片描述
不光是这个依赖下的 META-INF/spring.factories 被读取到,所有 Spring Boot Starter 下的 META-INF/spring.factories 都会被读取到。

第 4 步 :

到这里可能面试官会问你:spring.factories 中这么多配置,每次启动都要全部加载么?

很明显,这是不现实的。我们 debug 到后面你会发现,configurations 的值变小了。

在这里插入图片描述
因为,这一步有经历了一遍筛选过滤,@ConditionOnXXX 中的所有条件都满足,该类才会生效。

Spring Boot 提供的条件注解如下:

@ConditionalOnBean:当容器里有指定 Bean 的条件下
@ConditionalOnMissingBean:当容器里没有指定 Bean 的情况下
@ConditionalOnSingleCandidate:当指定 Bean 在容器中只有一个,或者虽然有多个但是指定首选 Bean
@ConditionalOnClass:当类路径下有指定类的条件下
@ConditionalOnMissingClass:当类路径下没有指定类的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径是否有指定的值
@ConditionalOnExpression:基于 SpEL 表达式作为判断条件
@ConditionalOnJava:基于 Java 版本作为判断条件
@ConditionalOnJndi:在 JNDI 存在的条件下差在指定的位置
@ConditionalOnNotWebApplication:当前项目不是 Web 项目的条件下
@ConditionalOnWebApplication:当前项目是 Web 项 目的条件下

通过一个具体技术说明自动装配原理

第一步:先找到 springboot 项目中的启动类,根据启动类上方的 @SpringBootApplication 注解一层层的找到下图中的类。在这个类中有一个常量,其常量值是spring.factories文件的所在位置,在这个文件中定义了第三方依赖中所有技术的全路径名。

在这里插入图片描述

第二步:从spring.factories文件中随便找到一个技术,以redis为例,然后在当前springboot项目中双击Shift,在弹出的页面中搜索找到RedisAutoConfiguration类。如下图所示:

在这里插入图片描述
由RedisAutoConfiguration类上面的注解可知,RedisAutoConfiguration类有一个bean加载控制的注解。也就是说,当前类要想加载成bean,必须在当前项目中导入RedisOperations这个类,也就是当前类加载成bean的触发条件,而RedisOperations这个类在我们导入的redis的依赖包中。

在RedisAutoConfiguration类上方有一个 @EableConfigurationProperties 注解。进入@EableConfigurationProperties 注解里的RedisProperties类中,如下图所示, RedisProperties 类上方有一个 @ConfigurationProperties 注解,此注解用来将配置文件中前缀为 spring.redis 的配置值绑定到类中属性上。

但是可以发现,RedisProperties类里很多属性已经配置了默认值。也就是说,如果 springboot 配置文件中没有配置值,则 springboot 会采用 RedisProperties 类中属性的默认值来作为redis这项技术的默认配置值。

在这里插入图片描述

注意:

spring.factories 功能在 SpringBoot 2.7 已经废弃,并且在 SpringBoot 3.0
移除。但机制还是类似的。

上图中的RedisProperties类为本人书写,类中实际的属性要多的多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/109036.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

慢查询SQL如何优化

一.什么是慢SQL? 慢SQL指的是Mysql中执行比较慢的SQL,排查慢SQL最常用的方法是通过慢查询日志来查找慢SQL。Mysql的慢查询日志是Mysql提供的一种日志记录&#xff0c;它用来记录Mysql中响应时间超过long_query_time值的sql,long_query_time的默认时间为10s. 二.查看慢SQL是否…

机器学习——贝叶斯(三种分布)/鸢尾花分类分界图/文本分类应用

0、前言&#xff1a; 机器学习中的贝叶斯的理论基础是数学当中的贝叶斯公式。这篇博客强调使用方法&#xff0c;至于理论未作深究。机器学习中三种类型的贝叶斯公式&#xff1a;高斯分布&#xff08;多分类&#xff09;、多项式分布&#xff08;文本分类&#xff09;、伯努利分…

Spring的 webFlux 和 webMVC

看到一个测评文章&#xff0c;并发在300的时候webMVC 和 webFlux的处理能力不相上下&#xff0c; 当并发达到3000的时候, webFlux明显优于webMVC, 有图有真相&#xff0c; 我信了. webMVC 是 one-request-one thread 堵塞模式, flux是非阻塞模式&#xff0c; 是spring家族系列…

分布式运用之rsync远程同步

一、rsync的相关知识 1.1 rsync简介 rsync&#xff08;Remote Sync&#xff0c;远程同步&#xff09;是一个开源的快速备份工具&#xff0c;可以在不同主机之间镜像同步整个目录树&#xff0c;支持增量备份&#xff0c;并保持链接和权限&#xff0c;且采用优化的同步算法&am…

GaussDB(DWS)云原生数仓技术解析:湖仓一体,体验与大数据互联互通

文章目录 前言一、关于数据仓库需求场景分类二、数据仓库线下部署场景2.1、线下部署场景介绍及优劣势说明2.2、线下部署场景对应的客户需求 三、数据仓库公有云部署场景3.1、公有云部署场景介绍及优劣势说明3.2、公有云部署场景对应的客户需求 四、为何重视数据共享&#xff08…

Python编程指南:利用HTTP和HTTPS适配器实现智能路由

嗨&#xff0c;爬虫大佬们&#xff01;今天我要为大家分享一篇关于如何利用HTTP和HTTPS适配器来实现智能路由的Python编程指南。在现代互联网应用中&#xff0c;路由功能起着至关重要的作用&#xff0c;而利用Python编程语言实现智能路由则可以为我们的应用带来更高的灵活性和性…

一阶微分方程

目录 可分离变量的方程 齐次微分方程 一阶线性微分方程 伯努科方程 全微分方程 可分离变量的方程 可分离变量的方程是一种常见的一阶常微分方程类型&#xff0c;其特点是可以通过将变量分离到方程的两侧&#xff0c;从而可以分别对各自变量进行积分。一般形式的可分离变量…

企业架构LNMP学习笔记45

失效机制&#xff08;了解&#xff09; 1&#xff09;如果key过期了&#xff0c;value会及时删除么&#xff1f;空间会及时清理么&#xff1f; 2&#xff09;如果分配的存储空间&#xff0c;写满了&#xff0c;还允许写么&#xff1f; -m可以配置内存大小。 memcached 内部不…

第14章_瑞萨MCU零基础入门系列教程之QSPI

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

火山引擎边缘云助力智能科技赋予生活更多新意

当下&#xff0c;先进的科学技术使得我们的日常生活变得快捷、舒适。大到上百层智能大厦、高端公共场所、社会智能基础设施&#xff0c;小到智能家居监控、指纹密码锁等&#xff0c;在这个充满想象力的时代&#xff0c;科技以更加智能化的方式改变和守护我们的生活。 引入智能…

一线大厂Redis高并发缓存架构实战与性能优化

多级缓存架构 缓存设计 缓存穿透 缓存穿透是指查询一个根本不存在的数据&#xff0c; 缓存层和存储层都不会命中&#xff0c; 通常出于容错的考虑&#xff0c; 如果从存储层查不到数据则不写入缓存层。 缓存穿透将导致不存在的数据每次请求都要到存储层去查询&#xff0c; 失…

Windows 下 MySQL 8.1 图形化界面安装、配置详解

首先我们下载安装包 官方下载链接&#xff1a; MySQL :: Begin Your Download 网盘链接: https://pan.baidu.com/s/1FOew6-93XpknB-bYDhDYPw 提取码: brys 外网下载慢的同学可以使用上述网盘链接 下载完成后我们双击安装包即可进入安装界面 点击next 勾选同意协议&#…