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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Golang安装

目录 Go安装下载安装Go Go安装 下载安装Go 地址&#xff1a;https://studygolang.com/dl 1、根据系统来选择下载包。 2、我是Window&#xff0c;所以直接下载windows的安装包来安装。 3、在控制台窗口输入“go version”可查看Go版本&#xff0c;检测是否安装成功。 4、配置…

【环境配置】使用Docker搭建LAMP环境

这篇文章不是介绍DOCKER是什么&#xff0c;也不是阐述DOCKER的核心&#xff1a;镜像/容器和仓库之间的关系,它只是一篇让刚刚接触DOCKER的初学者&#xff0c;在没有完全了解DOCKER是什么之前,也能尽快的在Linux系统下面通过DOCKER来搭建一个LAMP环境&#xff0c;这是其一&#…

Open3D(C++) 根据索引提取点云

目录 一、功能概述1、主要函数2、源码二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。爬虫网站自重,把自己当个人 一、功能概述 1、主要函数 std::shared_ptr<PointCloud> SelectByIn

IDEA安装热部署插件JRebel详解

JRebel 简介 JRebel是一套JavaEE开发工具。JRebel允许开发团队在有限的时间内完成更多的任务修正更多的问题&#xff0c;发布更高质量的软件产品。 JRebel是收费软件&#xff0c;用户可以在JRebel官方站点下载30天的评估版本。 Jrebel 可快速实现热部署&#xff0c;节省了大量重…

代码随想录算法训练营第二十五天 | 读PDF复习环节3

读PDF复习环节3 本博客的内容只是做一个大概的记录&#xff0c;整个PDF看下来&#xff0c;内容上是不如代码随想录网站上的文章全面的&#xff0c;并且PDF中有些地方的描述&#xff0c;是很让我疑惑的&#xff0c;在困扰我很久后&#xff0c;无意间发现&#xff0c;其网站上的讲…

前端html中让两个或者多个div在一行显示,用style给div加上css样式

文章目录 前言一、怎么让多个div在一行显示 前言 DIV是层叠样式表中的定位技术&#xff0c;全称DIVision&#xff0c;即为划分。有时可以称其为图层。DIV在编程中又叫做整除&#xff0c;即只得商的整数。 DIV元素是用来为HTML&#xff08;标准通用标记语言下的一个应用&#x…

图像处理之hough圆形检测

hough检测原理 点击图像处理之Hough变换检测直线查看 下面直接描述检测圆形的方法 基于Hough变换的圆形检测方法 对于一个半径为 r r r&#xff0c;圆心为 &#xff08; a , b &#xff09; &#xff08;a,b&#xff09; &#xff08;a,b&#xff09;的圆&#xff0c;我们将…

别再分库分表了,试试TiDB!

什么是NewSQL 传统SQL的问题 升级服务器硬件 数据分片 NoSQL 的问题 优点 缺点 NewSQL 特性 NewSQL 的主要特性 三种SQL的对比 TiDB怎么来的 TiDB社区版和企业版 TIDB核心特性 水平弹性扩展 分布式事务支持 金融级高可用 实时 HTAP 云原生的分布式数据库 高度兼…

M 芯片的 macos 系统安装虚拟机 centos7 网络配置

centos 安装之前把网络配置配好或者是把网线插好 第一步找到这个 第二步打开网络适配器 选择图中所指位置 设置好之后 开机启动 centos 第三步 开机以后 编写网卡文件保存 重启网卡就可以了&#xff0c;如果重启网卡不管用&#xff0c;则重启虚拟机即可 “ ifcfg-ens160 ” 这…

HTML快速学习

目录 一、网页元素属性 1.全局属性 2.标签 2.1其他标签 2.2表单标签 2.3图像标签 2.4列表标签 2.5表格标签 2.6文本标签 二、编码 1.字符的数字表示法 2.字符的实体表示法 三、实践一下 一、网页元素属性 1.全局属性 id属性是元素在网页内的唯一标识符。 class…

iOS开发-实现获取下载主题配置动态切换主题

iOS开发-实现获取下载主题配置动态切换主题 iOS开发-实现获取下载主题配置更切换主题&#xff0c;主要是通过请求服务端配置的主题配置、下载主题、解压保存到本地。通知界面获取对应的图片及颜色等。 比如新年主题风格&#xff0c;常见的背景显示红色氛围图片、tabbar显示新…

【002 操作系统】进程的状态及状态转换图?

一、进程的状态 1. 创建状态 2. 就绪状态 3. 运行状态 4. 阻塞状态 5. 终止状态 图源&#xff1a;进程、线程基础知识全家桶&#xff0c;30 张图一套带走_Linux_小林coding_InfoQ写作社区 NULL -> 创建状态&#xff1a;一个新进程被创建时的第一个状态&#xff1b; 创建状态…

LT6911C 是一款HDMI 1.4到双端口MIPIDSI/CSI或者LVDS加音频的一款高性能芯片

LT6911C 1.描述&#xff1a; LT6911C是一款高性能的HDMI1.4到MIPIDSI/CSI/LVDS芯片&#xff0c;用于VR/智能手机/显示器应用程序。对于MIPIDSI/CSI输出&#xff0c;LT6911C具有可配置的单端口或双端口MIPIDSI/CSI&#xff0c;具有1个高速时钟通道和1个~4个高速数据通道&#…

nacos源码打包及相关配置

nacos 本地下载后&#xff0c;需要 install 下&#xff1a; mvn clean install -Dmaven.test.skiptrue -Dcheckstyle.skiptrue -Dpmd.skiptrue -Drat.skiptruenacos源码修改后&#xff0c;重新打包生成压缩包命令&#xff1a;在 distribution 目录中运行&#xff1a; mvn -Pr…

Java 源码打包 降低jar大小

这里写目录标题 Idea maven 插件配置pom.xml 配置启动技巧 Idea maven 插件配置 pom.xml 配置 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><!-- 只…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(11)-Fiddler设置安卓手机抓包,不会可是万万不行的!

1.简介 Fiddler不但能截获各种浏览器发出的 HTTP 请求&#xff0c;也可以截获各种智能手机发出的HTTP/ HTTPS 请求。 Fiddler能截获 Android 和 Windows Phone 等设备发出的 HTTP/HTTPS 请求。 今天宏哥讲解和分享Fiddler 如何截获安卓移动端发出的 HTTP/HTTPS 请求。 2.环…

Python基于PyTorch实现卷积神经网络回归模型(CNN回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 卷积神经网络&#xff0c;简称为卷积网络&#xff0c;与普通神经网络的区别是它的卷积层内的神经元只覆…

抖音seo短视频矩阵系统源码开发解析---多账号授权管理

本文开发语音使用PHP语言开发&#xff0c;梅雨plum框架自主研发&#xff0c;文末另附开发技巧 抖音SEO短视频矩阵系统源码开发解析是一种基于抖音平台的短视频排名优化技术&#xff0c;通过对抖音算法的分析和抖音用户行为的研究&#xff0c;提供一种基于“流量矩阵”的短视频管…

通过STM32内部ADC将烟雾传感器发送的信号值显示在OLED上

一.CubeMX配置 首先我们在CubeMX配置ADC1, 设置一个定时器TIM2定时1s采样一次以及刷新一次OLED&#xff0c; 打开IIC用于驱动OLED显示屏。 二.程序 在Keil5中添加好oled的显示库&#xff0c;以及用来显示的函数、初始化函数、清屏函数等。在主程序中初始化oled,并将其清屏。…

二维深度卷积网络模型下的轴承故障诊断

1.数据集 使用凯斯西储大学轴承数据集&#xff0c;一共有4种负载下采集的数据&#xff0c;每种负载下有10种 故障状态&#xff1a;三种不同尺寸下的内圈故障、三种不同尺寸下的外圈故障、三种不同尺寸下的滚动体故障和一种正常状态 2.模型&#xff08;二维CNN&#xff09; 使…