SpringBoot(八) --- SpringBoot原理

news2025/6/6 22:25:22

目录

一、配置优先级

二、Bean的管理

1. Bean的作用域

2. 第三方Bean

三、SpringBoot原理

1. 起步依赖

2. 自动配置

3.  自动配置原理分析

3.1 源码解析

3.2 @Conditional


一、配置优先级

SpringBoot项目当中支持三类配置文件:

  • application.properties

  • application.yml

  • application.yaml

如果这三种配置文件同时存在,并且都配置了同一属性,如:Tomcat端口号,到底哪一份配置文件生效呢?

如下图所示,在application.properties配置文件中端口号设置为8081,在application.yml和application.yaml中端口号设置为8082。发现运行的端口号为8081.

properties、yaml、yml三种配置文件,优先级最高的是properties。

当properties不存在时,yaml、yml两种配置文件同时存在。会发现端口号为8083。

yaml、yml 两种配置文件,优先级最高的是yml。

总结:

配置文件的优先级为:properties配置文件、yml配置文件、yaml配置文件。但是目前主流使用的的配置文件为yml格式的。

二、Bean的管理

IOC容器中管理的就是Bean对象。

1. Bean的作用域

IOC容器中,默认bean对象是单例的 (只有一个实例对象)。Spring中支持五种作用域,后三种作用域在Web环境下才生效。(Web环境指的是传统Web开发,Spring环境指的是利用SSM框架开发的Web项目)。

可以借助Spring中的@Scope注解来配置作用域。

当设置Bean对象为单例时,例如下述代码:

//默认bean的作用域为:singleton (单例)
@RestController
@RequestMapping("/depts")
public class DeptController {

    @Autowired
    private DeptService deptService;

    public DeptController(){
        System.out.println("DeptController constructor ....");
    }

    //省略其他代码...
}

测试类如下:

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

    @Autowired
    private ApplicationContext applicationContext; //IOC容器对象

    //bean的作用域
    @Test
    public void testScope(){
        for (int i = 0; i < 10; i++) {
            DeptController deptController = applicationContext.getBean(DeptController.class);
            System.out.println(deptController);
        }
    }
}

结果如下图,可以发现,每一次创建的Bean实例都是同一个。

如果设置Bean的作用域非单例:

@Scope("prototype") //bean作用域为非单例
@RestController
@RequestMapping("/depts")
public class DeptController {

    @Autowired
    private DeptService deptService;

    public DeptController(){
        System.out.println("DeptController constructor ....");
    }

    //省略其他代码...
}

结果如下图,可以发现,IOC容器创建了多个Bean实例,每一次使用Bean对象就会创建一个新的实例。

2. 第三方Bean

之前所配置的Bean,像controller、service,dao三层体系下编写的类,这些类都是我们在项目当中自己定义的类(自定义类)。当我们要声明这些bean,也非常简单,我们只需要在类上加上@Component以及它的这三个衍生注解(@Controller@Service@Repository),就可以来声明这个bean对象了。

当某个类不是我们自己编写的,而是我们引入的第三方依赖当中提供的,那么此时我们是无法使用 @Component 及其衍生注解来声明bean的,此时就需要使用@Bean注解来声明bean 了。

此时有两种方式来声明第三方类的Bean,一种是在启动类中直接声明这个Bean【不推荐】,另一种是将第三方的Bean对象进行集中管理,通过@Configuration 注解声明一个配置类。【推荐】。

这里只介绍第二种方式。创建一个包,专门用来存在配置类,下面代码是将阿里云操作的工具类进行Bean注入。

@Configuration
public class OSSConfig {
    @Bean
    public AliyunOSSOperator aliyunOSSOperator(AliyunOSSProperties ossProperties) {
        return new AliyunOSSOperator(ossProperties);
    }
}

这是将Redis的相关第三方类进行Bean注入:

@Configuration
@Slf4j
public class RedisConfiguration {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        log.info("开始创建redis模版对象..");

        RedisTemplate redisTemplate = new RedisTemplate<>();
        // 设置redis的连接工厂对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 设置redis key的序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

然后,就可以直接在Controller层使用这个第三方类,例如下面代码:

@RestController("userShopController")
@RequestMapping("/user/shop")
@Slf4j
public class ShopController {

    private static final String KET = "SHOP_STATUS";

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 获取店铺营业状态
     */
    @GetMapping("/status")
    public Result getStatus() {
        Integer status = (Integer) redisTemplate.opsForValue().get(KET);
        log.info("获取营业状态为:{}", status == 1? "营业中" : "已打样");
        return Result.success(status);
    }
}

三、SpringBoot原理

Spring中的所有框架都是基于一个基础框架SpringFramework(也就是Spring框架)。SpringBoot框架的底层同样也是SpringFramework。

SpringBoot框架之所以使用起来更简单更快捷,是因为SpringBoot框架底层提供了两个非常重要的功能:一个是起步依赖,一个是自动配置

通过SpringBoot所提供的起步依赖,就可以大大的简化pom文件当中依赖的配置,从而解决了Spring框架当中依赖配置繁琐的问题。通过自动配置的功能就可以大大的简化框架在使用时bean的声明以及bean的配置。我们只需要引入程序开发时所需要的起步依赖,项目开发时所用到常见的配置都已经有了,我们直接使用就可以了。

1. 起步依赖

假如我们没有使用SpringBoot,用的是Spring框架进行web程序的开发,此时我们就需要引入web程序开发所需要的一些依赖。

但是如果使用SpringBoot,当我们引入了 spring-boot-starter-web 之后,maven会通过依赖传递特性,将web开发所需的常见依赖都传递下来。就不需要我们一个一个的去引用了。

简单理解就是,假如你想吃一份火锅。传统方式(老Spring)下,你需要单独下单锅底、肉、蔬菜等等东西,同时还要考虑选的菜品适不适合这个锅底等等。但是如果有了SpringBoot的起步依赖,就相当于你直接点了一个火锅套餐,你不需要考虑任何东西,只需要说一声“我要一个spring-boot-starter-web套餐”,后台就会自动将Web开发所需要的东西打包好。不需要一个一个找依赖,也不用担心版本冲突。

2. 自动配置

SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。

例如,我们要将一个对象转为json,直接注入一个Gson,然后就可以直接使用了。而我们在我们整个项目中,也并未配置Gson这个类型的bean,为什么可以直接注入使用呢? 原因就是因为这个bean,springboot中已经帮我们自动配置完毕了,我们是可以直接使用的。

自动配置是Spring Boot在启动时,根据你项目的实际依赖​(类路径上有啥)和当前环境​(比如有没有配数据源URL),​自动判断并创建好一大堆常用的Bean(对象)和配置。它背后靠一堆@ConditionalOn...(条件满足才生效)的智能开关实现。

3.  自动配置原理分析

3.1 源码解析

要搞清楚SpringBoot的自动配置原理,要从SpringBoot启动类上使用的核心注解@SpringBootApplication开始分析:

元注解就是在注解上的注解,是必需的,不再解释。

先来看第一个注解:@SpringBootConfiguration:

@SpringBootConfiguration注解上使用了@Configuration,表明SpringBoot启动类就是一个配置类。

@Indexed注解,是用来加速应用启动的(不用关心)。

再来看@ComponentScan注解:

@ComponentScan注解是用来进行组件扫描的,扫描启动类所在的包及其子包下所有被@Component及其衍生注解声明的类。

SpringBoot启动类,之所以具备扫描包功能,就是因为包含了@ComponentScan注解。

最后来看@EnableAutoConfiguration注解(自动配置核心注解):

@EnableXxxxx这种格式的注解说白了就是第三方依赖中提供的注解,指定要导入哪些Bean对象或配置类,在使用的时候在启动类上加上@EnableXxxxx注解即可,@SpringBootApplication注解上加了@EnableAutoConfiguration注解,就会自动传递到启动类上。

@EnableAutoConfiguration注解上使用了@Import注解(Import注解才是真正用来导入类的注解,@EnableXxxx只是将其包装了一下)。

AutoConfigurationImportSelector类是ImportSelector接口的实现类。

AutoConfigurationImportSelector类中重写了ImportSelector接口的selectImports()方法,selectImports()方法底层调用getAutoConfigurationEntry()方法,获取可自动配置的配置类信息集合。

getAutoConfigurationEntry()方法通过调用getCandidateConfigurations(annotationMetadata, attributes)方法获取在配置文件中配置的所有自动配置类的集合。

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports配置文件中会指定许多第三方的配置类,例如第三方依赖Gson的配置类:GsonAutoConfiguration。

打开第三方依赖中提供的GsonAutoConfiguration类,可以发现GsonAutoConfiguration类上,添加了注解@AutoConfiguration,因此该类是个配置类

自动配置的原理就是在配置类中定义一个@Bean标识的方法,而Spring会自动调用配置类中使用@Bean标识的方法,并把方法的返回值注册到IOC容器中。

自动配置源码小结:

自动配置原理源码入口就是 @SpringBootApplication 注解,在这个注解中封装了3个注解,分别是:

  • @SpringBootConfiguration

    • 声明当前类是一个配置类

  • @ComponentScan

    • 进行组件扫描(SpringBoot中默认扫描的是启动类所在的当前包及其子包)

  • @EnableAutoConfiguration

      在实现类重写的selectImports()方法,读取当前项目下所有依赖jar包中META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports两个文件里面定义的配置类(配置类中定义了@Bean注解标识的方法)。

    • 封装了@Import注解(Import注解中指定了一个ImportSelector接口的实现类)

当SpringBoot程序启动时,就会加载配置文件当中所定义的配置类,并将这些配置类信息(类的全限定名)封装到String类型的数组中,最终通过@Import注解将这些配置类全部加载到Spring的IOC容器中,交给IOC容器管理。

但是并不是把文件中的所有Bean都注册到IOC容器当中,因为在声明Bean对象的时候,会有一个@Conditional开头的注解,这个注解的作用就是按照指定的条件进行装配,只有满足条件,,响应的Bean才会注册到IOC容器当中。

3.2 @Conditional

  • 作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring的IOC容器中。

  • 位置:方法、类

  • @Conditional本身是一个父注解,派生出大量的子注解:

    • @ConditionalOnClass:判断环境中有对应字节码文件,才注册bean到IOC容器。

    • @ConditionalOnMissingBean:判断环境中没有对应的bean(类型或名称),才注册bean到IOC容器。

    • @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。

@ConditionalOnClass注解

@Configuration
public class HeaderConfig {

    @Bean
    @ConditionalOnClass(name="io.jsonwebtoken.Jwts")//环境中存在指定的这个类,才会将该bean加入IOC容器
    public HeaderParser headerParser(){
        return new HeaderParser();
    }
    
    //省略其他代码...
}

@ConditionalOnMissingBean注解(最常用)

@Configuration
public class HeaderConfig {
        
    @Bean
    @ConditionalOnMissingBean //不存在该类型的bean,才会将该bean加入IOC容器
    public HeaderParser headerParser(){
        return new HeaderParser();
    }
    
    //省略其他代码...
}

此时再来看看GsonAutoConfiguration这个配置类,@EnableConfigurationProperties(GsonProperties.class),这个注解明确告知SpringBoot框架,GsonProperties类是一个配置属性类(标注了 @ConfigurationProperties需要将配置文件(如application.yml)中前缀匹配的属性注入到该类的字段中:        

自动配置原理简要可体现为下图:

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

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

相关文章

C# 类和继承(抽象成员)

抽象成员 抽象成员是指设计为被覆写的函数成员。抽象成员有以下特征。 必须是一个函数成员。也就是说&#xff0c;字段和常量不能为抽象成员。必须用abstract修饰符标记。不能有实现代码块。抽象成员的代码用分号表示。 例如&#xff0c;下面取自一个类定义的代码声明了两个抽…

鸿蒙仓颉语言开发实战教程:商城登录页

听说Pura80要来了&#xff1f;感觉华为的新品像下饺子一样&#xff0c;让人目不暇接&#xff0c;每隔几天就有发布会看&#xff0c;真不错呀。 节后第一天&#xff0c;为了缓解大家假期的疲惫&#xff0c;咱们今天做点简单的内容&#xff0c;就是商城的登录页面。 其实这一次分…

JavaScript 数组与流程控制:从基础操作到实战应用

在 JavaScript 编程的世界里&#xff0c;数组是一种极为重要的数据结构&#xff0c;它就像是一个有序的 “收纳盒”&#xff0c;能够将多个值整齐地存储起来。而流程控制语句则像是 “指挥官”&#xff0c;能够按照特定的逻辑对数组进行遍历和操作。接下来&#xff0c;就让我们…

SkyWalking架构深度解析:分布式系统监控的利器

一、SkyWalking概述 SkyWalking是一款开源的APM(应用性能监控)系统&#xff0c;专门为微服务、云原生和容器化架构设计。它由Apache软件基金会孵化并毕业&#xff0c;已成为分布式系统监控领域的明星项目。 核心特性 ‌分布式追踪‌&#xff1a;跨服务调用链路的完整追踪‌服务…

vue2中的render函数

<script> export default {components: {},name: "renderElems",render (h, context) {return this.$attrs.vnode;},updated() {} } </script> <style scoped> </style>分析一下上面.vue组件&#xff1a; 组件结构&#xff1a; 这是一个非…

PARADISE:用于新生儿缺氧缺血性脑病(HIE)疾病识别与分割的个性化和区域适应性方法|文献速递-深度学习医疗AI最新文献

Title 题目 PARADISE: Personalized and regional adaptation for HIE disease identification and segmentation PARADISE&#xff1a;用于新生儿缺氧缺血性脑病&#xff08;HIE&#xff09;疾病识别与分割的个性化和区域适应性方法 1 文献速递介绍 缺氧缺血性脑病&…

WordPress子主题RiPro-V5van无授权全开源版(源码下载)

WordPress子主题RiPro-V5van无授权全开源版&#xff0c;直接上使用方法:WordPress后台上传就行 这个主题是1.0版本开源的&#xff0c;有能力的可以二次开发一下加一些自己喜欢的功能。 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/90952148 更多资…

StoreView SQL,让数据分析不受地域限制

作者&#xff1a;章建&#xff08;处知&#xff09; 引言 日志服务 SLS 是云原生观测和分析平台&#xff0c;为 Log、Metric、Trace 等数据提供大规模、低成本、实时的平台化服务。SLS 提供了多地域支持【1】&#xff0c;方便用户可以根据数据源就近接入 SLS 服务&#xff0c…

UCRT 和 MSVC 的区别(Windows 平台上 C/C++ 开发相关)

UCRT 和 MSVC 是与 Windows 平台上 C/C 开发相关的两个重要概念&#xff0c;它们都属于 Microsoft 的开发工具链的一部分。下面详细解释它们的含义、区别以及用途。 一、UCRT&#xff08;Universal C Runtime&#xff09; 1. 含义&#xff1a; UCRT&#xff08;Universal C …

rabbitmq Fanout交换机简介

给每个服务创建一个队列&#xff0c;然后每个业务订阅一个队列&#xff0c;进行消费。 如订单服务起个多个服务&#xff0c;代码是一样的&#xff0c;消费的也是同一个队列。加快了队列中的消息的消费速度。 可以看到两个消费者已经在消费了

JAVA-springboot JUnit单元测试

SpringBoot从入门到精通-第9章 JUnit单元测试 一、JUnit与单元测试 JUnit是一个开源的测试框架&#xff0c;虽然可以用于测试大多数编程语言的应用程序&#xff0c;但特别适合用于测试Java语言的应用程序。 软件测试一般分为4个阶段&#xff0c;即单元测试、集成测试、系统测…

PyCharm中运行.py脚本程序

1.最近在弄一个python脚本程序&#xff0c;记录下运行过程。 2.编写的python程序如下 # # Copyright 2017 Pixar # # Licensed under the terms set forth in the LICENSE.txt file available at # https://openusd.org/license. # # Check whether this script is being run …

[论文阅读] 人工智能+项目管理 | 当 PMBOK 遇见 AI:传统项目管理框架的破局之路

当PMBOK遇见AI&#xff1a;传统项目管理框架的“AI适配指南” 论文信息 arXiv:2506.02214 Is PMBOK Guide the Right Fit for AI? Re-evaluating Project Management in the Face of Artificial Intelligence Projects Alexey Burdakov, Max Jaihyun Ahn Subjects: Software …

Gateway 搭建

1.创建 moudle 命名为 gateway 2,pom中引入依赖 网关依赖&#xff1b;注册中心依赖等 <!-- 网关依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></d…

pytorch基本运算-导数和f-string

引言 在前序对机器学习的探究过程中&#xff0c;我们已经深刻体会到人工智能到处都有微分求导运算&#xff0c;相关文章链接包括且不限于&#xff1a; BP神经网络 逻辑回归 对于pytorch张量&#xff0c;求导运算必不可少&#xff0c;所以本次就专门来学习一下。 f-string的用…

5.RV1126-OPENCV 图形计算面积

一.图形面积、弧长计算介绍 前面我们已经把图形轮廓的检测、画框等功能讲解了一遍。这次主要结合轮廓检测的 API 去计算图形的面积&#xff0c;这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能&#xff0c;常用的 API 如 contourArea…

【Android基础回顾】一:Binder机制是什么?有什么用?

Android中的Binder机制是Android系统中最核心和最基础的进程间通讯机制。 1 什么是进程间通讯机制(IPC)&#xff1f; 众所周知&#xff0c;Android系统基于Linux开发&#xff0c;Linux系统里面本来就有进程间通讯机制。 1.1 Linux的IPC(Inter-Process Communication)概览 它…

LeetCode 高频 SQL 50 题(基础版) 之 【高级查询和连接】· 上

题目&#xff1a;1731. 每位经理的下属员工数量 题解&#xff1a; select employee_id,name,reports_count,average_age from Employees t1,(select reports_to,count(*) reports_count,round(avg(age)) average_agefrom Employeeswhere reports_to is not nullgroup by repor…

资产智慧管理安全监测中心

在数字经济高速发展的今天&#xff0c;资产管理的智能化已成为企业降本增效的核心竞争力。从智慧园区到古建筑群&#xff0c;从交通枢纽到城市电网&#xff0c;资产智慧管理安全监测中心正以物联网、人工智能、数字孪生等技术为支撑&#xff0c;构建起资产全生命周期的“智慧大…

从零开始的云计算——番外实战,iptables防火墙项目

目录 一网络规划 二项目要求 三环境准备 1防火墙设置 2PC1设置 3PC2设置 4服务器S1设置 四环境检测 1内网链接 2外网连接 五防火墙配置及测试 1内部网络中的pc1采用SNAT访问外部互联网&#xff0c;但是无法ping到内部网关。 ​编辑​编辑 2内部网络服务器s1通过DN…