【JavaEE】Spring Boot 自动装配原理(源码分析)

一. 前言

  • 我们在写Spring Boot的程序代码的时候, 可以注入很多我们没有定义过的Bean.
  • 例如:
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    public DataSourceTransactionManager transactionManager;
    @Autowired
    public AutowireCapableBeanFactory autowireCapableBeanFactory;
  • 这些对象是什么时候注入进去的, Spring 是如何做的,我们可以通过阅读源码来解决这个问题.

二.Spring Boot自动装配的原理分析.

2.1 源码阅读

  • 要搞清楚自动装配的原因, 我们需要去分析Spring Boot的启动类.

  • @SpringBootApplication 标注的类 就是SpringBoot项目的启动类, 这个注解也是SpringBoot实现自动配置的核心
    在这里插入图片描述

  • 元注解:

    • JDK中提供了4个标准的用来对注解类型进行注解的注解类, 我们称之为 meta-annotation(元注
      解)
    • @Target 描述注解的使用范围(即被修饰的注解可以用在什么地方).
    • @Retention 描述注解保留的时间范围.
    • @Documented 描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息
    • @Inherited 使被它修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则
      其子类将自动具有该注解
      )
  • @SpringBootConfiguration 在这里插入图片描述

里面就是@Configuration, 标注当前类为配置类, 其实只是做了一层封装改了个名字而已.
(@Indexed注解,是用来加速应用启动的, 不用关心), 本质上就是将启动类交给Spring进行管理

  • @ComponentScan (包扫描)
    可以通过 basePackageClasses 或 basePackages 来定义要扫描的特定包, 如果没有定义
    特定的包, 将从声明该注解的类的包开始扫描, 这也是为什么SpringBoot项目声明的注解类必须要在启动类的目录下,这样通过@Controller , @Service , @Repository , @Component , @Configuration ,@Bean标注的类/对象,就会被Spring进行管理. excludeFilters 自定义过滤器, 通常用于排除一些类, 注解等

2.2 @EnableAutoConfiguration(自动装配的核心注解)

  • 观察@EnableAutoConfiguration注解的实现:
    在这里插入图片描述
    这个注解包含两部分:

2.2.1@AutoConfigurationPackage

源码如下:
在这里插入图片描述
这个注解主要是导入一个配置文件 AutoConfigurationPackages.Registrar.class
在这里插入图片描述

  • registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry): 这个方法是ImportBeanDefinitionRegistrar接口的一部分,用于在Spring应用程序上下文中注册额外的bean定义。当一个@Configuration类使用了@Import注解并且指定了实现ImportBeanDefinitionRegistrar接口的类时,这个方法会被调用。在这个例子中,它使用PackageImports(一个假定存在的辅助类)来获取包名,并将这些包名作为字符串数组传递给另一个重载的register方法,以便在注册表中注册这些包中的类作为Spring bean定义。

  • determineImports(AnnotationMetadata metadata): 这个方法是DeterminableImports接口的一部分,用于确定哪些类应该被导入到当前的@Configuration类或@SpringBootApplication类中。在这个例子中,它返回了一个单例集合(Set),其中包含了一个PackageImports对象。这个对象封装了应该被扫描的包的信息,这样Spring就能自动发现并注册这些包中的@Component、@Service、@Repository等注解的类。

Registrar实现了 ImportBeanDefinitionRegistrar 类, 就可以被注解@Import导⼊到spring
容器里. (String[])(new PackageImports(metadata)).getPackageNames().toArray(new
String[0]) : 当前启动类所在的包名. 所以:@AutoConfigurationPackage 就是将启动类所在的包下⾯所有的组件都扫描注冊到spring 容器中.

2.2.2 @Import({AutoConfigurationImportSelector.class})

  • 使用@Import注解,导入了实现ImportSelector接口的实现类.
    在这里插入图片描述

  • selectImports() 方法底层调用 getAutoConfigurationEntry() 方法, 获取可自动配置的配置类信息集合.
    在这里插入图片描述

  • getAutoConfigurationEntry() 方法通过调用getCandidateConfigurations(annotationMetadata, attributes) 方法获取在配置文件中配置的所有自动配置类的集合
    在这里插入图片描述

  • getCandidateConfigurations 方法的功能:

    • 获取所有基METAINF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imp
      orts 文件, META-INF/spring.factories 文件中配置类的集合. 在引入的起步依赖中, 通常都有包含以上两个文件
      在这里插入图片描述

这里面包含了很多第三方依赖的配置文件(连续按两下shift可以查看对应的源码)

  1. 在加载自动配置类的时候, 并不是将所有的配置全部加载进来, 而是通过@Conditional等注解的判
    断进行动态加载.@Conditional是spring底层注解, 意思就是根据不同的条件, 来进行自己不同的条件判断,如果满足指定的条件,那么配置类里边的配置才会生效.
  2. META-INF/spring.factories文件是Spring内部提供的一个约定俗成的加载方式, 只需要在模块的
    META-INF/spring.factories文件中配置即可, Spring就会把相应的实现类注入到Spring容器中.
    注: 会加载所有jar包下的classpath路径下的META-INF/spring.factories文件, 这样文件不止一个
  • 比如 Redis的配置: RedisAutoConfiguration
    在这里插入图片描述
    由于我这个项目的pom依赖中,没有加入redis相关的依赖, 所以会根据注解@ConditionalOnMissingBean不进行加载

三.总结.

  • SpringBoot 自动配置原理的大概流程如下:
    在这里插入图片描述
    当SpringBoot程序启动时, 会加载配置文件当中所定义的配置类, 通过 @Import 注解将这些配置类全
    部加载到Spring的IOC容器中, 交给IOC容器管理

  • SpringBoot的自动配置原理源码口是 @SpringBootApplication 注解, 这个注解封装了3个注

    • @SpringBootConfiguration 标志当前类为配置类
    • @ComponentScan 进行包扫描(默认扫描的是启动类所在的当前包及其子包)
    • @EnableAutoConfiguration
      • @Import 注解 : 读取当前项目下所有依赖jar包中 META-INF/spring.factories ,
        METAINF/spring/org.springframework.boot.autoconfigure.AutoConfigurat
        ion.imports 两个文件里面定义的配置类(配置类中定义了 @Bean 注解标识的方法)
      • @AutoConfigurationPackage : 把启动类所在的包下面所有的组件都注入到 Spring
        容器中

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode】翻转二叉树

目录 一、题目二、解法完整代码 一、题目 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1] 示例 2: 输入:root…

一个C++模板工厂的编译问题的解决。针对第三方库的构造函数以及追加了的对象构造函数。牵扯到重载、特化等

一窥模板的替换和匹配方式:偏特化的参数比泛化版本的还要多:判断是不是std::pair<,>。_stdpair模板参数太多-CSDN博客 简介 在一个项目里,调用了第三封的库,这个库里面有个类用的很多,而且其构…

Java语言程序设计基础篇_编程练习题**15.18(使用鼠标来移动一个矩形)

**15.18(使用鼠标来移动一个矩形) 请编写一个程序显示一个矩形。可以使用鼠标单击矩形内部并且拖动(即按住鼠标移动)矩形到鼠标的位置。鼠标点成为矩形的中央习题思路: 新建一个面板Pane(),新建一个Rectangle() 为Rectangle注册…

Cxx Primer-chap7

类的基本思想是数据抽象和封装,前者强调interface和implement分离,后者在此基础上,强调访问控制符(存疑)。同时类的实现者和使用者考虑的角度不同,前者考虑实现效率,后者仅需关注功能即可&#…

猫头虎分享已解决Bug || JSON Parsing Errors: json: cannot unmarshal

猫头虎分享已解决Bug 🐯 || JSON Parsing Errors: json: cannot unmarshal 摘要 在后端开发过程中,处理JSON数据时经常会遇到解析错误,尤其是json: cannot unmarshal错误。这类问题往往由于JSON数据格式与Go语言结构体不匹配引起。今天&…

vue字段判断是否可以鼠标悬浮或者点击跳转

通过字段判断是否可以鼠标悬浮展示颜色 是否点击 <span :class"[converBond.stkindustry ! null ? hoverSpan:,]"click"converBond.stkindustry ! null ?goToIndustry(converBond.stkindustryname,converBond.stkindustry):false">{{converBon…

尚品汇-sku存入Redis缓存(二十三)

目录&#xff1a; &#xff08;1&#xff09;分布式锁改造获取sku信息 &#xff08;2&#xff09;使用Redisson 分布式锁 AOP实现缓存 &#xff08;3&#xff09;定义缓存aop注解 &#xff08;1&#xff09;分布式锁改造获取sku信息 前面学习了本地锁的弊端&#xff0c;…

怎么使用github上传XXX内所有文件

要将 目录中的所有文件上传到 GitHub&#xff0c;你可以按照以下步骤进行&#xff1a; 创建一个新的 GitHub 仓库 登录到你的 GitHub 账户。 点击右上角的加号&#xff08;&#xff09;&#xff0c;选择 “New repository”。 输入仓库名称&#xff08;例如&#xff1a;202407…

走难而正确的路并持之以恒

走难而正确的路并持之以恒 接近八月&#xff0c;台风频繁。气象台说台风“格美”今夜将至&#xff0c;往粤北走&#xff0c;而留在粤东的将是持续的高温。高温的广州&#xff0c;这几晚的天空惊喜不断&#xff0c;成片的火烧云&#xff0c;站在猎德大桥观望&#xff0c;丹红的凤…

数字图像处理笔记(一)---- 图像数字化与显示

系列文章目录 数字图像处理学习笔记&#xff08;一&#xff09;---- 图像数字化与显示 数字图像处理笔记&#xff08;二&#xff09;---- 像素加图像统计特征 数字图像处理笔记&#xff08;三) ---- 傅里叶变换的基本原理 文章目录 系列文章目录前言一、数字图像处理二、图像数…

字符串相加(leetcode算法题)

各位老铁早上好&#xff0c;今天来分享一下我前两天做的leetcode的题目&#xff0c;我个人觉得这两道题目挺经典的&#xff0c;所以打算写这篇博客进行总结&#xff0c;希望各位老铁看完我这篇博客能有所收获。 字符串相加 题目链接 题目要求&#xff1a;你不能使用任何內建…

【Vue实战教程】之 Vue3 新特性详解

1 为什么要用Vue3 在学习Vue3的新特性之前&#xff0c;我们先来看一下Vue3设计的目的是什么&#xff0c;为什么要对Vue2做出很大的改变&#xff0c;以及Vue3到底解决了什么问题。像Vue这样全球闻名的前端框架&#xff0c;在任何一次改动时&#xff0c;设计者都是经过深思熟虑的…

Kithara和Halcon (二)

Kithara使用Halcon QT 进行二维码实时识别 目录 Kithara使用Halcon QT 进行二维码实时识别Halcon 简介以及二维码检测的简要说明Halcon 简介Halcon的二维码检测功能 Qt应用框架简介项目说明关键代码抖动测试测试平台&#xff1a;测试结果&#xff1a; 开源源码 Halcon 简介以…

vue3+vite纯前端实现自动触发浏览器刷新更新版本内容,并在打包时生成版本号文件

前言 在前端项目中&#xff0c;有时候为了实现自动触发浏览器刷新并更新版本内容&#xff0c;可以采取一系列巧妙的措施。我的项目中是需要在打包时候生成一个version.js文件&#xff0c;用当前打包时间作为版本的唯一标识&#xff0c;然后打包发版 &#xff0c;从实现对版本更…

基于SpringBoot的矩形范围面时空分析-以震中附近历史地震为例

目录 前言 1、分析的必要性 2、分析的紧迫性 一、数据库物理模型及空间分析实现 1、数据库物理模型 2、空间数据库中的空间查询分析 二、Java后台程序开发 1、模型层设计 2、业务层的设计与实现 三、WebGIS功能设计与实现 1、同时展示4幅地图 2、初始化地图 3、展示…

动态创建标签jQuery效果

动态创建标签jQuery效果https://www.bootstrapmb.com/item/14832 使用jQuery来动态创建HTML标签并添加效果是一种常见的方法。以下是一个简单的示例&#xff0c;说明如何使用jQuery来动态创建<div>标签&#xff0c;并给它们添加一些基本的效果。 1. 创建一个新的<di…

go语言day17 通道channel

Golang-100-Days/Day16-20(Go语言基础进阶)/day18_channel通道.md at master rubyhan1314/Golang-100-Days (github.com) go语言day09 通道 协程的死锁-CSDN博客 channel for range 循环通道对象 单向通道 单项通道常用于函数参数&#xff0c;只是用来限定在函数中只能进行通道…

Langchain核心模块与实战[8]:RAG检索增强生成[loader机制、文本切割方法、长文本信息处理技巧]

Langchain核心模块与实战[8]:RAG(Retrieval Augmented Generation,检索增强生成) RAG(Retrieval-Augmented Generation)技术是一种结合检索和生成功能的自然语言处理(NLP)技术。该技术通过从大型外部数据库中检索与输入问题相关的信息,来辅助生成模型回答问题。其核心…

Mysql中(基于GTID方式)实现主从复制,单主复制详细教程

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️创作…

《深入探秘Java中的枚举:掌握Enum的魔力》

目录 &#x1f4dd; 枚举枚举的定义枚举的使用1、表示一组固定常量2、实现接口3、枚举与策略模式4、EnumSet5、EnumMap &#x1f4ce; 参考文章 &#x1f600; 准备好了吗&#xff1f;让我们一起步入这座Java神奇的城堡&#xff0c;探寻枚举&#xff08;Enum&#xff09;这个强…