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

拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配

963034f17590412b808770f619144970.png

🎉🎉欢迎光临,终于等到你啦🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟持续更新的专栏《Spring 狂野之旅:从入门到入魔》 🚀

本专栏带你从Spring入门到入魔 

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽http://suzee.blog.csdn.net/

 


 

springboot帮我们做了什么

一个字--自动!

通常搭建一个基于spring的web应用,我们需要做以下工作:

1、pom文件中引入相关jar包,包括spring、springmvc、redis、mybaits、log4j、mysql-connector-java 等等相关jar ...

2、配置web.xml,Listener配置、Filter配置、Servlet配置、log4j配置、error配置 ...

3、配置数据库连接、配置spring事务

4、配置视图解析器

5、开启注解、自动扫描功能

6、配置完成后部署tomcat、启动调试

......

这些都是Spring boot在背后默默为我们做的工作

那 有没有想过为什么? 

本文给大家来解读Spring的源码 拆解他的自动配置 一步一步解释为什么Springboot为何那么强大

 

 

进入他的细节源码之前 首先关注 ---架构

cb4b233de36d4b1c8bab048bf0e7cf94.png

解读SpringBootApplication

@Target(ElementType.TYPE)            // 注解的适用范围,其中TYPE用于描述类、接口(包括包注解类型)或enum声明
@Retention(RetentionPolicy.RUNTIME)  // 注解的生命周期,保留到class文件中(三个生命周期)
@Documented                          // 表明这个注解应该被javadoc记录
@Inherited                           // 子类可以继承该注解
@SpringBootConfiguration             // 继承了Configuration,表示当前是注解类
@EnableAutoConfiguration             // 开启springboot的注解功能,springboot的四大神器之一,其借助@import的帮助
@ComponentScan(excludeFilters = {    // 扫描路径设置(具体使用待确认)@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}

@Configuration

这里的@Configuration 对我们来说不陌生,它就是 JavaConfig 形式的 Spring Ioc 容器的配置类使用的那个@Configuration,SpringBoot 社区推荐使用基于 JavaConfig 的配置形式,所以,这里的启动类标注了@Configuration 之后,本身其实也是一个 IoC 容器的配置类。 举几个简单例子回顾下,XML 跟 config 配置方式的区别:

表达形式层面 基于 XML 配置的方式是这样:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"default-lazy-init="true"><!--bean定义-->
</beans>

而基于 JavaConfig 的配置方式是这样:

@Configuration
public class MockConfiguration{//bean定义
}

任何一个标注了@Configuration 的 Java 类定义都是一个 JavaConfig 配置类。

注册 bean 定义层面 基于 XML 的配置形式是这样:

<bean id="mockService" class="..MockServiceImpl">...
</bean>

而基于 JavaConfig 的配置形式是这样的:

@Configuration
public class MockConfiguration{@Beanpublic MockService mockService(){return new MockServiceImpl();}
}

任何一个标注了@Bean 的方法,其返回值将作为一个 bean 定义注册到 Spring 的 IoC 容器,方法名将默认成该 bean 定义的 id。

表达依赖注入关系层面 为了表达 bean 与 bean 之间的依赖关系,在 XML 形式中一般是这样:

<bean id="mockService" class="..MockServiceImpl"><propery name ="dependencyService" ref="dependencyService" />
</bean><bean id="dependencyService" class="DependencyServiceImpl"></bean>

而基于 JavaConfig 的配置形式是这样的:

@Configuration
public class MockConfiguration{@Beanpublic MockService mockService(){return new MockServiceImpl(dependencyService());}@Beanpublic DependencyService dependencyService(){return new DependencyServiceImpl();}
}

@ComponentScan:


@ComponentScan注解用于指定Spring容器扫描组件的基础包路径。它会自动扫描指定包及其子包下的类,并将被@Component及其派生注解标注的类识别为Spring的组件,将其实例化并纳入容器管理。

// 在包com.example中定义了两个被@Component注解标记的类:UserService和UserRepository// UserService.java
package com.example;import org.springframework.stereotype.Component;@Component
public class UserService {// ...
}// UserRepository.java
package com.example;import org.springframework.stereotype.Component;@Component
public class UserRepository {// ...
}// AppConfig.java
package com.example;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan("com.example") // 指定扫描的基础包路径
public class AppConfig {// 配置其他的Bean
}

@ComponentScan的原理可以从源代码的角度来解释。在Spring的源代码中,@ComponentScan注解被解析为一个Bean扫描器。当Spring容器启动时,扫描器会根据指定的包路径,将带有@Component及其派生注解的类解析为BeanDefinition对象,并注册到BeanFactory中。这样,Spring容器就知道这些类是组件,并可以对其进行实例化和管理。

 

@EnableAutoConfiguration:


@EnableAutoConfiguration注解用于启用Spring Boot的自动配置功能。它会根据项目的依赖和配置,自动加载和配置一系列的Spring Bean,简化了项目的配置过程。

@EnableAutoConfiguration的原理可以从源代码的角度来解释。在Spring Boot的源代码中,@EnableAutoConfiguration注解被解析为一个自动配置处理器。当Spring Boot应用启动时,处理器会根据classpath下的META-INF/spring.factories文件中的配置,加载并执行一系列的自动配置类。这些自动配置类根据约定和条件,自动创建和配置相应的Bean对象,完成项目的自动化配置。

Import(AutoConfigurationImportSelector.class)注解:

4645b32fc9024aff95da548d4c880141.png

图中看出 AutoConfigurationImportSelector 继承了 DeferredImportSelector 继承了 ImportSelector

ImportSelector有一个方法为:selectImports。

@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AnnotationAttributes attributes = getAttributes(annotationMetadata);List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);configurations = removeDuplicates(configurations);Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = filter(configurations, autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations, exclusions);return StringUtils.toStringArray(configurations);}

AutoConfigurationImportSelector是Spring Boot内部的一个选择器类,它会根据项目的依赖和配置,选择要自动配置的类。该选择过程是基于条件注解(如@ConditionalOnClass、@ConditionalOnProperty等)进行的,只有满足条件的自动配置类才会被选择。

 

@AutoConfigurationPackage

// 在包com.example中定义了一个主配置类ApplicationConfig// ApplicationConfig.java
package com.example;import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@AutoConfigurationPackage // 标注了@AutoConfigurationPackage注解
public class ApplicationConfig {// 主配置类的内容// ...
}

当Spring Boot启动时,它会扫描并解析主配置类ApplicationConfig。在解析过程中,Spring Boot会检测到@AutoConfigurationPackage注解,并执行相应的处理。

@AutoConfigurationPackage注解被解析为一个特殊的Bean定义处理器。处理器会读取主配置类ApplicationConfig的包路径(com.example),并将该包路径注册到Spring的BeanFactory中。

注册完成后,Spring容器会将com.example包及其子包作为组件扫描的范围。这意味着Spring会扫描该包下的所有类,并根据条件注解(如@ConditionalOnClass@ConditionalOnMissingBean等)来决定是否自动配置相应的Bean。

通过将主配置类所在的包及其子包作为自动配置的包,我们可以确保自动配置类能够正确地扫描和应用到我们的应用程序中。

 

 

 

相关文章:

拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…...

中国银行信息系统应用架构发展历程

概述&#xff1a; 从 20 世纪 80 年代开始至今&#xff0c;我国银行业信息化历程已 有四十年历史。虽然相对于发达国家来讲&#xff0c;我国银行业务信 息化起步较晚&#xff0c;但发展速度很快&#xff0c; 目前我国一些大型商业银行的信息化程度已经处于全球领先水平。 “银行…...

掌握Go语言:探索Go语言指针,解锁高效内存操作与动态数据结构的奥秘(19)

指针是一个变量&#xff0c;它存储了另一个变量的地址。在Go语言中&#xff0c;指针提供了直接访问内存地址的能力&#xff0c;允许程序直接操作内存&#xff0c;这在某些场景下非常有用。 Go语言指针的详细使用方法 声明指针 可以使用*符号来声明指针变量&#xff0c;例如&…...

大数据面试题 —— Zookeeper

目录 ZooKeeper 的定义ZooKeeper 的特点ZooKeeper 的应用场景你觉得Zookeeper比较重要的功能ZooKeeper 的选举机制 ***zookeeper主节点故障&#xff0c;如何重新选举&#xff1f;ZooKeeper 的监听原理 ***zookeeper集群的节点数为什么建议奇数台 ***ZooKeeper 的部署方式有哪几…...

【安全类书籍-6】僵尸网络:网络程序杀手

目录 内容 用处 下载链接 内容 这本书着重探讨以下几个主题: 1. 僵尸网络基础:介绍僵尸网络的基本构成、运作机制以及在全球网络空间中的影响和威胁程度。 2. 僵尸网络技术剖析:详细分析僵尸网络的组件,如命令控制中心(C&C)、恶意软件传播途径、感染节点的招募和…...

文件的创建与删除

文件的创建 使用File类创建一个文件对象&#xff0c;例如&#xff1a;File filenew File("c:\\myletter" , "letter.txt"); public boolean createNewFile();/*如果c:\myletter目录中没 有名字为letter.txt文件&#xff0c;文件对象file调用createNewFil…...

图论题目集一(代码 注解)

目录 题目一&#xff1a; 题目二&#xff1a; 题目三&#xff1a; 题目四&#xff1a; 题目五&#xff1a; 题目六&#xff1a; 题目七&#xff1a; 题目一&#xff1a; #include<iostream> #include<queue> #include<cstring> using namespace st…...

解释MVC和MVVM架构模式

一、解释MVC和MVVM架构模式 MVC和MVVM都是常见的前端架构模式&#xff0c;用于抽象分离并解决特定问题。这两种模式在结构上具有一定的相似性&#xff0c;但在细节和数据处理方式上存在一些差异。 MVC&#xff0c;即Model-View-Controller&#xff0c;是一种用于应用程序分层…...

OLLAMA:如何像云端一样运行本地大语言模型

简介&#xff1a;揭开 OLLAMA 本地大语言模型的神秘面纱 您是否曾发现自己被云端语言模型的网络所缠绕&#xff0c;渴望获得更本地化、更具成本效益的解决方案&#xff1f;那么&#xff0c;您的探索到此结束。欢迎来到 OLLAMA 的世界&#xff0c;这个平台将彻底改变我们与大型…...

React全家桶及原理解析-lesson4-Redux

lesson4-react全家桶及原理解析.mov React全家桶及原理解析 React全家桶及原理解析 课堂⽬标资源起步Reducer 什么是reducer什么是reduceRedux 上⼿ 安装reduxredux上⼿检查点react-redux 异步代码抽取Redux拓展 redux原理 核⼼实现中间件实现redux-thunk原理react-redux原理 实…...

电商api数据接口技术开发来赞达lazada通过商品ID抓取商品详情信息item_get请求key接入演示

要获取Lazada的商品详情&#xff0c;你需要使用item_get请求。首先&#xff0c;你需要注册一个开发者账号并获取API密钥&#xff08;App Key和App Secret&#xff09;。然后&#xff0c;你可以使用以下Python代码示例来获取商品详情&#xff1a; # coding:utf-8 ""&…...

零基础入门多媒体音频(2)-音频焦点2

说实话&#xff0c;android的代码是越来越难以阅读。业务函数里面狗皮膏药似的补丁与日俱增。继上篇简要介绍音频焦点的文章&#xff0c;这篇文章的主要内容是分析audiofocus的实现。看了一下午的相关代码都没找到做audiofocus策略的核心逻辑。目前能看懂的大概包含下面两个逻辑…...

Spark杂谈

文章目录 什么是Spark对比HadoopSpark应用场景Spark数据处理流程什么是RDDSpark架构相关进程入门案例&#xff1a;统计单词数量Spark开启historyServer 什么是Spark Spark是一个用于大规模数据处理的统一计算引擎Spark一个重要的特性就是基于内存计算&#xff0c;从而它的速度…...

【PyTorch】进阶学习:一文详细介绍 torch.save() 的应用场景、实战代码示例

【PyTorch】进阶学习&#xff1a;一文详细介绍 torch.save() 的应用场景、实战代码示例 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程…...

私域流量运营的关键要素和基本步骤

解锁增长的四大关键&#xff1a; 关键要素一&#xff1a;精准营销 精准营销是私域流量运营的核心所在。通过精细化运营和个性化服务&#xff0c;企业可以将普通用户转化为忠实粉丝&#xff0c;提高用户的粘性和转化率。采用数据驱动的精准营销策略&#xff0c;深度挖掘用户需求…...

k8s部署hadoop

&#xff08;作者&#xff1a;陈玓玏&#xff09; 配置和模板参考helm仓库&#xff1a;https://artifacthub.io/packages/helm/apache-hadoop-helm/hadoop 先通过以下命令生成yaml文件&#xff1a; helm template hadoop pfisterer-hadoop/hadoop > hadoop.yaml用kube…...

deepspeed分布式训练在pytorch 扩展(PyTorch extensions)卡住

错误展示&#xff1a; Using /root/.cache/torch_extensions/py310_cu121 as PyTorch extensions root...
 Using /root/.cache/torch_extensions/py310_cu121 as PyTorch extensions root...
 错误表现&#xff1a; 出现在多卡训练过程的pytorch 扩展&#xff0c;deepspee…...

Rust 的 HashMap

在 Rust 中&#xff0c;HashMap 是一个从键&#xff08;key&#xff09;映射到值&#xff08;value&#xff09;的数据结构。它允许你以 O(1) 的平均时间复杂度存储、检索和删除键值对。HashMap 实现了 std::collections::HashMap 结构体&#xff0c;通常通过 use std::collect…...

exporter方式监控达梦数据库

蓝鲸监控 随着国产化和信创的深入&#xff0c;开始普遍使用国产化数据库–如达梦数据库&#xff0c;蓝鲸平台默认没有对其进行监控&#xff0c;但是平台了提供监控告警的能力。比如脚本采集&#xff0c;脚本的是一种灵活和快速的监控采集方式&#xff0c;不同层的监控对象都可…...

供应链安全之被忽略的软件质量管理平台安全

背景 随着我国信息化进程加速&#xff0c;网络安全问题更加凸显。关键信息基础设施和企业单位在满足等保合规的基础上&#xff0c;如何提升网络安全防御能力&#xff0c;降低安全事件发生概率&#xff1f;默安玄甲实验室针对SonarQube供应链安全事件进行分析&#xff0c;强调供…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

【WebSocket】SpringBoot项目中使用WebSocket

1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖&#xff0c;添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器

一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下&#xff0c;音视频内容犹如璀璨繁星&#xff0c;点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频&#xff0c;到在线课堂中知识渊博的专家授课&#xff0c;再到影视平台上扣人心弦的高清大片&#xff0c;音…...