SpringBoot底层原理

SpringBoot底层原理

一 配置优先级

1.配置方式

Springboot中支持三种配置方式,分别为:

  • application.properties
  • application.yml
  • application.yaml

2.配置优先级

当存在多份配置文件时,配置文件会按照它们的优先级生效。

优先级从高到底分别为:application.peoperties>application.yml>application.yaml

目前 application.yml 是最主流的方式

3.其他配置方式

Springboot除了以上常见的三种配置方式之外,还支持Java系统属性配置和命令行参数配置。

1.Java系统属性配置示例

# 在 java 命令后使用 —D 命令,然后书写需要配置的属性即可
# 示例中配置了项目的运行端口为8081,即server.port=8081
java -Dserver.port=8081 -jar [packageName].jar

2.命令行参数配置示例

# 在jar包名称之后,使用双横杠(--),后面紧跟配置的参数即可
java -jar [packageName].jar --server.port=8082

二 Bean管理

1.获取bean对象

默认情况下,Springboot项目在启动时会自动创建bean,并且将这些bean都存放在IOC容器中。

如果想手动获取这些bean,则可以通过以下几种示例。

首先需要注入ApplicationContext对象。

Spring框架中,ApplicationContext是一个接口,代表了Spring容器,它负责管理Spring应用程序中所有的bean,同时提供了一些方法来获取Bean,注册Bean,是整个Spring应用的核心。

默认情况下,一个Bean的名称是它的类名名称,然后将首字母小写。

例如 DeptController,它在IOC容器中的默认名称为 deptController

@Autowired
private ApplicationContext applicationContext;
@Test
void test1(){//1.根据bean的名称来获取bean对象EmpServiceImpl empServiceImpl1= (EmpServiceImpl) applicationContext.getBean("empServiceImpl");System.out.println(empServiceImpl1);//2.根据bean的类型来获取bean对象EmpServiceImpl empServiceImpl2= applicationContext.getBean(EmpServiceImpl.class);System.out.println(empServiceImpl2);//3.根据bean的类型和名称来获取bean对象// 以下方法和示例,在bean的默认名称被修改且有多个同类型的bean时,尤为有用。EmpServiceImpl empServiceImpl3= applicationContext.getBean("empServiceImpl",EmpServiceImpl.class);System.out.println(empServiceImpl3);
}

运行以上示例,可以看出,bean在IOC容器中,默认是单例存在的。
在这里插入图片描述如果想要实现每次使用时都是一个新的bean,则需要通过bean的作用域来进行配置。

2.bean的作用域

在Spring中,bean支持五种作用域,后三种在web环境下才能生效。

在这里插入图片描述

默认情况下,Bean对象在项目启动时就会默认实例化。如果不希望在项目启动时就初始化,可以使用@Lazy注解,让Bean对象延迟初始化,直到第一次使用该Bean时才会进行初始化。

@Service
@Lazy
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService{//code...
}

设置Bean的作用域,则需要通过@Scope注解来实现。

以下示例中,我们将Bean的作用域设置为 prototype,即每次使用该Bean时都会创建新对象。

@Service
@Scope("prototype")
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService{//code...
}

现在再次运行前边获取Bean对象的代码示例,可以发现,三次获取到的Bean对象,已经不是同一个。
在这里插入图片描述

3.声明第三方bean

如果要申明的Bean来自第三方,是无法通过@Component及衍生注解来申明的,这个时候就需要使用@Bean注解。

以 SAXReader 类为例,创建一个返回值为SAXReader对象的方法,方法名称就是以后被ICO管理的Bean对象名称。

//将方法的返回值交给IOC容器管理,称为IOC容器的Bean对象
@Bean
public SAXReader saxReader(){return new SAXReader();
}

在以后需要用到 SAXReader 对象的时候,直接注入即可,不用去实例化。

@Autowired
private SAXReader saxReader;
@Test
void test2() throws DocumentException {Document document = saxReader.read("xxx");
}

注意:一般情况下,我们通常会将所有需要申明的第三方bean对象统一放在一个配置类中,这样更加方便维护。

@Configuration
public class BeanAutoConfig {// 可以通过@Bean注解的 name /value 属性来定义bean的名称// 默认情况下,bean的名称就是方法名@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}}

在声明第三方bean对象时,如果需要进行依赖注入,则只需要指定方法形参即可。Spring会根据类型进行自动装配。

// EmpServiceImpl对象是要注入的bean对象
@Bean
public RestTemplate restTemplate(EmpServiceImpl empServiceImpl){empServiceImpl.[xxx];return new RestTemplate();
}

三 Springboot原理

1.Springboot起步依赖

Springboot整合了以前web开发需要用的一些依赖项,目前使用Springboot开发web项目,只需要引入 spring-boot-start-web 依赖即可。
在这里插入图片描述
归根结底,SPringboot起步依赖的原理就是maven的依赖传递

2.自动配置

当Springboot项目启动后,Springboot中的一些配置类,bean对象就会自动存入到IOC容器中,不需要我们手动去申明。从而简化了开发,省去了繁琐的配置。

3.管理第三方包中的Bean

1.配置实现方式1:@ComponentScan 组件扫描

在启动类上使用 @ComponentScan注解,重新配置包扫描路径。@ComponentScanbasePackages参数支持数据格式,当有多个第三方包时,可使用数组形式申明。

@ComponentScan(basePackages = "xxx1")

@ComponentScan(basePackages = {"xxx1","xxx2"
})

注意:使用@ComponentScan申明时,当前Springboot项目中的包路径也必须包含在内,否则当前项目中的bean将会被无法识别。

缺点:当项目较大时,引入大量的第三方依赖,此时启动类将会显得臃肿。

2.配置实现方式2:@Import 组件导入

使用@Import导入的类会被Spring加载到容器中。可以导入普通类,配置类,以及 ImportSelector 接口的实现类,支持数组。

@Import({xx1.class,xx2.class})

实现ImportSelector 接口,这里最核心的就是 selectImports方法,它返回了需要创建Bean对象的全部类。

public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//此处的数组内容为需要导入的Bean对象的全类名,有多少写多少return new String[]{"springboot.demo.GoodStudent"};}
}

然后在启动类上使用@Import注解即可。

@Import({MyImportSelector.class})

单纯使用 @Import接口声明第三方Bean,缺点很明显。

3.配置实现方式3:第三方依赖提供注解

实际项目中,具体第三方依赖需要导入哪些Bean,只有第三方依赖自己知道。所以可以由第三方依赖提供注解,然后在项目中引入即可。

此类型注解一般均由 Enable 开头,原理是在自定义注解中封装 @Import 注解。

示例:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({MybatisPlusConfig.class,CorsConfig.class,SpringWebConfig.class,BeanAutoConfig.class,RedisConfig.class
})
public @interface EnableShawnConfig {}

在第三方依赖包中定义一个EnableShawnConfig注解,然后使用 @Import将需要配置的Bean对象都引入进来。最后再在项目中使用该注解即可。

@EnableShawnConfig
@SpringBootApplication
public class ShawnServerSystemApplication {public static void main(String[] args) {SpringApplication.run(ShawnServerSystemApplication.class, args);}
}

4.自动配置原理分析

Springboot核心注解:@SpringBootApplication

@SpringBootApplication下的重要注解:

  • @SpringBootConfiguration:申明当前注解也是一个配置类,因为@SpringBootConfiguration中也申明了@Configuration注解。所以可以直接在启动类中申明第三方的bean对象。
  • @EnableAutoConfiguration:Springboot自动配置的核心注解,它声明了@Import(AutoConfigurationImportSelector.class)AutoConfigurationImportSelectorImportSelector接口的实现类,实现了 selectImports 方法selectImports 方法返回了需要创建Bean对象的全部信息。
  • @ComponentScan:组件扫描,默认扫描当前引导类及其所在的子包。

自动配置最核心的注解就是@EnableAutoConfiguration,由源码可知,selectImports 方法会读取一个固定目录下后缀名为.imports的文件。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).getCandidates();Assert.notEmpty(configurations,"No auto configuration classes found in "+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "+ "are using a custom packaging, make sure that file is correct.");return configurations;
}

springboot3.x中,META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中,配置了需要创建Bean对象的全类名

在Springboot2.x中,是通过两个关键文件来读取配置好的全类名的。
在这里插入图片描述
spring.factories 是早起Springboot版本中自动配置的文件,在后续版本中已经逐渐不再使用。

5.@Conditinal注解

@Conditinal注解的作用:按照一定的条件判断,在满足条件后才会注册对应的Bean对象到IOC容器中

它可以作用在方法上。

@Conditinal本身是一个父级注解,它衍生除了很多子级注解

  • @ConditionalOnClass:判断环境中是否存在字节码文件,有则注册bean对象到IOC容器
  • @ConditionalOnMissingBean:判断环境中有没有对应的Bean(根据类型和名称),没有则注册Bean对象到IOC容器
  • @ConditionalOnProperty:判断配置文件中是否有对应属性和值,有则注册bean对象到IOC容器

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

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

相关文章

免费音频剪辑

在数字时代&#xff0c;音频剪辑已成为许多职业和爱好者不可或缺的技能。无论是制作播客、教育视频、还是进行广告宣传&#xff0c;高质量的音频剪辑都能为作品增色不少。今天&#xff0c;我要为大家强烈安利一款免费且功能强大的音频剪辑工具&#xff0c;它绝对是你办公桌上不…

ISO_IEC_18598-2016自动化基础设施管理(AIM)系统国际标准解读(一)

██ ISO_IEC_18598-2016是什么标准&#xff1f; ISO/IEC 18598国际标准是由ISO&#xff08;国际标准化组织&#xff09;/IEC&#xff08;国际电工委员会&#xff09;联合技术委员会1-信息技术的第25分委员会-信息技术设备互连小组制定的关于信息基础设施自动化管理的国际标准&…

备战蓝桥杯Day22 - 计数排序

计数排序问题描述 对列表进行排序&#xff0c;已知列表中的数范围都在0-100之间。设计时间复杂度为O(n)的算法。 比如列表中有一串数字&#xff0c;2 5 3 1 6 3 2 1 &#xff0c;需要将他们按照从小到大的次序排列&#xff0c;得到1 1 2 2 3 3 5 6 的结果。那么此时计数排序是…

python 使用curl_cffi 绕过jax3指纹-Cloudflare 5s盾

现在越来越多的网站已经能够通过JA3或者其他指纹信息&#xff0c;来识别你是不是爬虫了。传统的方式比如换UA&#xff0c;加代理是没有任何意义了&#xff0c;所以这个时候我们就需要使用到curl_cffi 了。 1.TLS 指纹是啥&#xff1f; 在绝大多数的网站都已经使用了 HTTPS&am…

一个脚本两步计算材料Raman谱(附数据处理和绘图脚本)

在以往推送中已经介绍了相当多的计算材料Raman的方法&#xff0c;使用的软件主要为Phonopy-Spectroscopy&#xff0c;相关软件还有vasp&#xff0c;phonopy&#xff0c;phono3py等。 Phonopy-Spectroscopy计算材料红外和Raman光谱 Phonopy-Spectroscopy 计算红外和拉曼光谱 也…

python绘制特殊的柱状图

我在使用python绘图时&#xff0c;想要这样绘图&#xff1a;每个组的所有数据放到一起&#xff0c;然后不同组进行比较。 类似这样的图。 然后 我搞了挺长时间&#xff0c;搞了一个类似的图&#xff0c;需要计算每个柱子的位置。 gpt提示词可以这样写: 把所有颜色相同的柱子放…

【MCAL】TC397+EB-tresos之CAN配置实战 - (CAN/CANFD)

本篇文章介绍了在TC397平台使用EB-tresos对CAN驱动模块进行配置的实战过程,不仅介绍了标准CAN的发送与接收&#xff0c;还介绍了CANFD的实现与调试以及扩展帧的使用。M_CAN是德国博世公司开发的IP&#xff0c;因为英飞凌的芯片完整的集成了这个IP&#xff0c;所以整体的配置都比…

4.关联式容器

关联式container STL中一些常见的容器&#xff1a; 序列式容器&#xff08;Sequence Containers&#xff09;&#xff1a; vector&#xff08;动态数组&#xff09;&#xff1a; 动态数组&#xff0c;支持随机访问和在尾部快速插入/删除。list&#xff08;链表&#xff09;&am…

【接口测试】常见HTTP面试题

目录 HTTP GET 和 POST 的区别 GET 和 POST 方法都是安全和幂等的吗 接口幂等实现方式 说说 post 请求的几种参数格式是什么样的&#xff1f; HTTP特性 HTTP&#xff08;1.1&#xff09; 的优点有哪些&#xff1f; HTTP&#xff08;1.1&#xff09; 的缺点有哪些&#x…

Nginx高级技巧:实现负载均衡和反向代理

文章目录 Nginx概述Nginx作用正向代理反向代理负载均衡动静分离 Nginx的安装 -->Docker3.1 安装Nginx3.2 Nginx的配置文件3.3 修改docker-compose文件 Nginx源码安装nginx常用命令nginx配置文件配置文件位置配置文件结构详情 Nginx的反向代理【重点】基于Nginx实现反向代理4…

会声会影2024中文官方网站https://wm.makeding.com/iclk/?zoneid=55677

会声会影2024在易用性方面做得非常出色&#xff0c;这也是它受到广大用户喜爱的一个重要原因。 首先&#xff0c;会声会影2024拥有直观的用户界面设计。软件的整体布局清晰明了&#xff0c;各个功能模块划分得十分合理。用户即使是第一次使用&#xff0c;也能够迅速找到所需的…

实战 | 使用YOLOv8图像分割实现路面坑洞检测(步骤 + 代码)

导 读 本文主要介绍使用YOLOv8图像分割实现路面坑洞检测&#xff08;步骤 代码&#xff09;。 背 景 如上图所示&#xff0c;现实生活中路面坑洞对车辆和驾驶员安全来说存在巨大隐患&#xff0c;本文将介绍如何使用YoloV8图像分割技术来检测路面坑洞&#xff0c;从而提示驾…

【大数据Hive】hive 多字段分隔符使用详解

目录 一、前言 二、hive默认分隔符规则以及限制 2.1 正常示例&#xff1a;单字节分隔符数据加载示例 2.2 特殊格式的文本数据&#xff0c;分隔符为特殊字符 2.2.1 文本数据的字段中包含了分隔符 三、突破默认限制规则约束 3.1 数据加载不匹配情况 1 3.2 数据加载不匹配…

理解python3中的回调函数

百度百科说&#xff1a;回调函数就是一个通过函数指针调用的函数。如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另一个函数&#xff0c;当这个指针被用来调用其所指向的函数时&#xff0c;我们就说这是回调函数。回调函数不是由该函数的实现方直接调用&#…

ctf_show笔记篇(web入门---php特性)

目录 php特性 89&#xff1a;直接数组绕过preg_match当遇到数组时会直接报错输出0 90&#xff1a;这里利用了intval的特性 91&#xff1a;这里需要细节一点 92-93&#xff1a;这两题的方法很多可以发散思维 94&#xff1a;还是利用小数绕过例如4476.0 95&#xff1a;这里…

【ArcGIS】统计格网中不同土地利用类型占比

基于ArcGIS统计格网中不同土地利用类型占比 数据准备ArcGIS操作步骤1、创建渔网&#xff08;Create Fishnet&#xff09;2、建立唯一标识3、选择格网4、提取不同类别土地利用类型5、各类用地面积计算 参考另&#xff1a;可能出现的问题总结Q1&#xff1a;ArcGIS获取唯一值&…

7.1.1 selenium介绍及安装chromedriver

目录 1. Selenium的用途 2. 安装Selenium库 3. 安装chromedriver 1. 查看谷歌版本号​编辑 2. 找到最新版本及下载 3. 配置环境变量 4. 检测是否配置成功 5. 用python初始化浏览器对象检测&#xff1a; 6. 参考链接 1. Selenium的用途 在前面我们提到&#xff1a;在我…

端智能:面向手机计算环境的端云协同AI技术创新

近年来&#xff0c;随着移动端设备软硬件能力的进步&#xff0c;移动端的算力有了很大提升&#xff0c;同时面向移动端的机器学习框架和模型轻量化技术越来越成熟&#xff0c;端上的AI能力逐渐进入大众视野&#xff0c;端智能在电商领域也开始逐步走向规模化应用。通过持续探索…

Leetcoder Day36| 动态规划part03

343. 整数拆分 给定一个正整数 n&#xff0c;将其拆分为至少两个正整数的和&#xff0c;并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 示例 1: 输入: 2输出: 1解释: 2 1 1, 1 1 1。 示例 2: 输入: 10输出: 36解释: 10 3 3 4, 3 3 4 36。说明: 你可以假设 …

Day04:APP架构小程序H5+Vue语言Web封装原生开发Flutter

目录 常见APP开发架构 APP-开发架构-原生态-IDEA APP-开发架构-Web封装-平台 APP-开发架构-H5&Vue-HBuilderX WX小程序-开发架构-Web封装-平台 WX小程序-开发架构-H5&Vue-HBuilderX 思维导图 章节知识点&#xff1a; 应用架构&#xff1a;Web/APP/云应用/三方服…