当前位置: 首页 > news >正文

SpringBoot自动装配介绍

aa2d47c285af433a80dba4ec4454759f.jpgSpringBoot是对Spring的一种扩展,其中比较重要的扩展功能就是自动装配:通过注解对常用的配置做默认配置,简化xml配置内容。本文会对Spring的自动配置的原理和部分源码进行解析,本文主要参考了Spring的官方文档。

 

 

自动装配的组件

SpringBoot自动装配通过多部分组件协调完成,这些组件主要有下面几种,这几种组件之间协调工作,最终完成了SpringBoot的自动装配。

 

@EnableAutoConfiguration:用于根据用户所引用的jar包自动装配Spring容器,比如用户在ClassPath中包含了HSQLDB,但是没有手动配置数据库连接,那么Spring会自动使用HSQLDB作为数据源。

@Condition:不同情况下按照条件进行装配,Spring的JdbcTemplate是不是在Classpath里面?如果是,并且DataSource也存在,就自动配置一个JdbcTemplate的Bean

@ComponentScan:扫描指定包下面的@Component注解的组件。

@EnableAutoConfiguration注解

Spring的自动装配发展大致可以分为三个阶段:

 

全手工配置的XML文件阶段,用户需要的Bean全部需要在XML文件中声明,用户手工管理全部的Bean。

半手工配置的注解阶段,用户可以安装需求Enable对应的功能模块,如添加@EnableWebMvc可以启用MVC功能。

全自动配置的SpringBoot,用户只需要引入对应的starter包,Spring会通过factories机制自动装配需要的模块。

全手工配置的XML文件示意图:

 

xml手工装配

 

半自动注解配置示意图:

 

半自动配置

 

全自动注解配置示意图:

 

全自动配置

 

Spring启用全自动配置功能的注解就是@EnableAutoConfiguration,应用添加了@EnableAutoConfiguration注解之后,会读取所有jar包下面的spring.factories文件,获取文件中配置的自动装配模块,然后去装配对应的模块。

 

@EnableAutoConfiguration的功能可总结为:使Spring启用factories机制导入各个starter模块的配置。

 

原理分析

通过上面的分析我们知道Spring的@EnableAutoConfiguration主要功能是使Spring启用factories机制导入各个starter模块的配置。下面我们会对@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 {};

}

@EnableAutoConfiguration注解的定义有两部分比较重要的内容:

@AutoConfigurationPackage:将添加该注解的类所在的package作为自动配置package进行管理。

@Import({AutoConfigurationImportSelector.class}):用于导入factories文件中的AutoConfiguration。

 

@Import({AutoConfigurationImportSelector.class})

首先我们需要知道@Import注解的作用,从字面意思就可以看出来,@Import用于把一个Bean注入到Spring的容器中,@Import可以导入三种类型的Bean:

 

导入普通的Bean,通常是@Configuration注解的Bean,也可以是任意的@Component组件类型的类。

导入实现了ImportSelector接口的Bean,ImportSelector接口可以根据注解信息导入需要的Bean。

导入实现了ImportBeanDefinitionRegistrar注解的Bean, ImportBeanDefinitionRegistrar接口可以直接向容器中注入指定的Bean。

@Import({AutoConfigurationImportSelector.class})中的AutoConfigurationImportSelector实现了ImportSelector接口,会按照注解内容去装载需要的Bean。

 

    public String[] selectImports(AnnotationMetadata annotationMetadata) {

        if (!this.isEnabled(annotationMetadata)) {

            return NO_IMPORTS;

        } else {

            // 获取需要自动装配的AutoConfiguration列表

            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);

            // 获取自动装配类的类名称列表

            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());

        }

    }

 

    // 获取需要自动装配的AutoConfiguration列表

    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {

        if (!this.isEnabled(annotationMetadata)) {

            return EMPTY_ENTRY;

        } else {

            // 获取注解中的属性

            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);

 

            // 获取所有META-INF/spring.factories中的AutoConfiguration类

            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

 

            // 删除重复的类

            configurations = this.removeDuplicates(configurations);

 

            // 获取注解中Execlud的类

            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);

            this.checkExcludedClasses(configurations, exclusions);

 

            // 移除所有被Exclude的类

            configurations.removeAll(exclusions);

 

            // 使用META-INF/spring.factories中配置的过滤器

            configurations = this.getConfigurationClassFilter().filter(configurations);

 

            // 广播相关的事件

            this.fireAutoConfigurationImportEvents(configurations, exclusions);

 

            // 返回符合条件的配置类。

            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);

        }

    }

@AutoConfigurationPackage

@AutoConfigurationPackage用于将添加该注解的类所在的package作为自动配置package进行管理,听起来是不是和@ComponentScan功能有所重复?我们来分析一下其具体实现,可以看到这个注解依旧是通过@Import注解向容器中注册Bean。

 

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@Import({Registrar.class})

public @interface AutoConfigurationPackage {

    String[] basePackages() default {};

 

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

}

@AutoConfigurationPackage注解导入了Registrar.class,其本质是一个ImportBeanDefinitionRegistrar,会把当前注解类所在的包注入到Spring容器中。

 

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

        Registrar() {

        }

 

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {

            AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));

        }

 

        public Set<Object> determineImports(AnnotationMetadata metadata) {

            return Collections.singleton(new AutoConfigurationPack

相关文章:

SpringBoot自动装配介绍

SpringBoot是对Spring的一种扩展&#xff0c;其中比较重要的扩展功能就是自动装配&#xff1a;通过注解对常用的配置做默认配置&#xff0c;简化xml配置内容。本文会对Spring的自动配置的原理和部分源码进行解析&#xff0c;本文主要参考了Spring的官方文档。 自动装配的组件 …...

1400*D. Candy Box (easy version)(贪心)

3 10 9 Example input 3 8 1 4 8 4 5 6 3 8 16 2 1 3 3 4 3 4 4 1 3 2 2 2 4 1 1 9 2 2 4 4 4 7 7 7 7 output 题意&#xff1a; n个糖果&#xff0c;分为多个种类&#xff0c;要求尽可能的多选&#xff0c;并且使得不同种类的数量不能相同。 解析&#xff1a; 记录每种糖…...

设计模式-备忘录模式在Java中使用示例-象棋悔棋

场景 备忘录模式 备忘录模式提供了一种状态恢复的实现机制&#xff0c;使得用户可以方便地回到一个特定的历史步骤&#xff0c;当新的状态无效 或者存在问题时&#xff0c;可以使用暂时存储起来的备忘录将状态复原&#xff0c;当前很多软件都提供了撤销(Undo)操作&#xff0…...

用合成数据训练托盘检测模型【机器学习】

想象一下&#xff0c;你是一名机器人或机器学习 (ML) 工程师&#xff0c;负责开发一个模型来检测托盘&#xff0c;以便叉车可以操纵它们。 ‌你熟悉传统的深度学习流程&#xff0c;已经整理了手动标注的数据集&#xff0c;并且已经训练了成功的模型。 推荐&#xff1a;用 NSDT设…...

人性-基本归因错误

定义 基本归因谬误指出&#xff0c;你评价别人的一个行为时&#xff0c;你会高估他的内部因素——比如性格的影响&#xff0c;低估外在的情景之类各种复杂因素的影响。 具体表现是对自己&#xff0c;我们很愿意分析复杂的原因&#xff1b;对别人&#xff0c;如果他一句话说的…...

游戏引擎:打造梦幻游戏世界的秘密武器

介绍 游戏引擎是游戏开发中不可或缺的工具&#xff0c;它为开发者提供了构建游戏世界所需的各种功能和工具。本文将介绍游戏引擎的概念、使用方法以及一个完整的游戏项目示例。 游戏引擎的概念 游戏引擎是一种软件框架&#xff0c;它提供了游戏开发所需的各种功能和工具&…...

ClickHouse(六):Clickhouse数据类型-1

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客 &…...

【Linux】网络基础

&#x1f34e;作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;Linux系统网络编程 文章目录 一、协议初识和网络协议分层&#xff08;TCP/IP四层模型&#xff09;认识协议TCP/IP五层&#xff08;或四层&#xff09;模型 二、认识MAC地址和IP地址认识MAC地址认识IP地址认…...

小程序-接口概率性接收不到参数

在小程序上调用一个接口&#xff0c;传入筛选条件&#xff0c;但返回结果却没有进行筛选&#xff0c;概率性出现这种情况&#xff0c;频率较低。 然后在postman调用该接口&#xff0c;调用很多很多次&#xff0c;发现也出现这种问题&#xff0c;看了代码&#xff0c;接口的传参…...

合作客户销售数据可视化分析

以一个案例进行实际分析&#xff1a; 数据来源&#xff1a;【地区数据分析】 以此数据来制作报表。 技巧一&#xff1a;词云图 以城市名称来显示合同金额的分布&#xff0c;合同金额越大&#xff0c;则城市文字显示越大。 技巧二&#xff1a;饼图 下面制定一个&#xff0c;合…...

git仓库迁移场景

1.git仓库迁移 代码仓库从公网迁移内网&#xff0c;内外网网络不通&#xff0c;而且必须保证代码完整&#xff0c;包括分支以及提交记录。具体步骤如下 1.1 拉取所有分支镜像 1.2 现在本地电脑新建文件夹 mkdir newdir1.3 进入新建文件 newdir 执行下面命令拉取所有镜像代码…...

【RabbitMQ】之持久化机制

目录 一、RabbitMQ 持久化机制 1、RabbitMQ 持久化概述2、队列持久化3、消息持久化4、交换器持久化 二、RabbitMQ 知识扩展 1、内存告警与内存换页2、磁盘告警与配置3、数据写入磁盘时机4、磁盘消息格式5、磁盘文件删除机制 一、RabbitMQ 持久化机制 1、RabbitMQ 持久化概述…...

【项目6 UI Demo】前端代码记录

前端代码记录 1.GridListItem中的布局 在这个Item中的布局采用的是VBox和HBox相结合的方式。相关的代码如下&#xff1a; <VBox class"sapUiTinyMargin"><HBox justifyContent"SpaceBetween"><Titletext"{ToolNumber}"wrapping…...

【计算机网络】应用层协议 -- HTTP协议

文章目录 1. 认识HTTP协议2. 认识URL3. HTTP协议格式3.1 HTTP请求协议格式3.2 HTTP响应协议格式 4. HTTP的方法5. HTTP的状态码6. HTTP的Header7. Cookie和Session 1. 认识HTTP协议 协议。网络协议的简称&#xff0c;网络协议是通信计算机双方必须共同遵守的一组约定&#xff0…...

了解Unity编辑器之组件篇Layout(八)

Layout&#xff1a;用于管理和控制UI元素的排列和自动调整一、Aspect Ratio Fitter&#xff1a;用于根据宽高比自动调整UI元素的大小 Aspect Mode&#xff1a;用于定义纵横比适配的行为方式。Aspect Mode属性有以下几种选项&#xff1a; &#xff08;1&#xff09;None&#xf…...

如何使用Flask-Mail来发送电子邮件

你知道如何使用Flask-Mail来发送电子邮件吗 Flask-Mail是一个用于Flask框架的扩展&#xff0c;它简化了在Flask应用程序中发送电子邮件的过程。通过使用Flask-Mail&#xff0c;你可以轻松地创建邮件消息对象&#xff0c;设置发件人、收件人、主题和正文&#xff0c;并使用SMTP服…...

【笔记】Java并发编程

为什么不建议使用Executors创建线程池分析 不建议使用Executors来创建线程池&#xff0c;主要是有两大原因第一个是问题回溯的问题&#xff0c;使用Executors都可以使用默认的情况&#xff0c;无法用户自定义线程名称不利于排查问题&#xff0c;第二个原因也是最主要原因就是线…...

Hive内部表和外部表

表类型详解 表分类 在Hive中,表类型主要分为两种 第一种&#xff1a;内部表 也叫管理表表目录会创建在集群上的{hive.metastore.warehouse.dir}下的相应的库对应的目录中。默认创建的表就是内部表 第二种&#xff1a;外部表 外部表需要使用关键字"external"&#xff…...

【面试题】与通义千问的芯片前端设计模拟面试归纳

这里是尼德兰的喵芯片设计相关文章,欢迎您的访问! 如果文章对您有所帮助,期待您的点赞收藏! 让我们一起为芯片前端全栈工程师而努力! 前言 两个小时,与chatGPT进行了一场数字IC前端设计岗的面试_尼德兰的喵的博客-CSDN博客 和GPT-3.5的回答可以对比品尝,味道更好。 模…...

无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本。npm.ps1 cannot be loaded

目录 原因 解决方法 提示 查看当前的执行策略命令 改回默认值 "Restricted"命令 这个错误提示是因为您的系统禁止执行 PowerShell 脚本。 原因 现用执行策略是 Restricted&#xff08;默认设置&#xff09; 解决方法 以管理员身份运行 PowerShell&#xff1a;右键…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...