Springboot原理之bean的依赖功能、自动配置

news2024/11/14 23:15:12

1. Bean管理

Spring 当中提供的注解 @Component 以及它的三个衍
生注解( @Controller @Service @Repository )来声明 IOC 容器中的 bean 对象,同时我们也学
习了如何为应用程序注入运行时所需要依赖的 bean 对象,也就是依赖注入 DI
我们今天主要学习 IOC 容器中 Bean 的其他使用细节,主要学习以下三方面:
1. 如何从 IOC 容器中手动的获取到 bean 对象
2. bean 的作用域配置
3. 管理第三方的 bean 对象

1.1 获取Bean

默认情况下, SpringBoot 项目在启动的时候会自动的创建 IOC 容器 ( 也称为 Spring 容器 ) ,并且在启动
的过程当中会自动的将 bean 对象都创建好,存放在 IOC 容器当中。应用程序在运行时需要依赖什么 bean
对象,就直接进行依赖注入就可以了。
而在 Spring 容器中提供了一些方法,可以主动从 IOC 容器中获取到 bean 对象,下面介绍 3 种常用方式,通过applicationcontext对象:
@Autowired
private ApplicationContext applicationContext ; //IOC 容器对象
1. 根据 name 获取 bean
        Object getBean ( String name )
2. 根据类型获取 bean
        < T > T getBean ( Class < T > requiredType )
3. 根据 name 获取 bean (带类型转换)
        < T > T getBean ( String name , Class < T > requiredType )

1.2 Bean作用域

在前面我们提到的 IOC 容器当中,默认 bean 对象是单例模式 ( 只有一个实例对象 ) 。那么如何设置 bean
对象为非单例呢?需要设置 bean 的作用域。
Spring 中支持五种作用域,后三种在 web 环境才生效:
1). 测试一
控制器
// 默认 bean 的作用域为: singleton ( 单例 )
@Lazy // 延迟加载(第一次使用 bean 对象时,才会创建 bean 对象并交给 ioc 容器管
理)
// @Scope ( "singleton" ) //单列是默认的,所以无需填写,若prototype...等可以填写
@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 );
                                }
                        }
}
注意事项:
IOC 容器中的 bean 默认使用的作用域: singleton ( 单例 )
默认 singleton bean ,在容器启动时被创建,可以使用 @Lazy 注解来延迟初始化 ( 延迟到
第一次使用时 )

1.3 第三方Bean

之前我们所配置的 bean ,像 controller service dao 三层体系下编写的类,这些类都是我们在项
目当中自己定义的类 ( 自定义类 ) 。当我们要声明这些 bean ,也非常简单,我们只需要在类上加上
@Component 以及它的这三个衍生注解( @Controller @Service @Repository ),就可以来声
明这个 bean对象了
pom.xml 文件中,引入 dom4j
dom4j 就是第三方组织提供的。 dom4j 中的 SAXReader 类就是第三方编写的。
当我们需要使用到 SAXReader 对象时,直接进行依赖注入是不是就可以了呢?
按照我们之前的做法,需要在 SAXReader 类上添加一个注解 @Component (将当前类交给 IOC 容器
管理)
结论:第三方提供的类是只读的。无法在第三方类上添加 @Component 注解或衍生注解。
那么我们应该怎样使用并定义第三方的 bean 呢?
如果要管理的 bean 对象来自于第三方(不是自定义的),是无法用 @Component 及衍生注解声明
bean 的,就需要用到 @Bean 注解。
解决方案 1 :在启动类上添加 @Bean 标识的方法
xml 文件:
测试类:
说明:以上在启动类中声明第三方 Bean 的作法,不建议使用(项目中要保证启动类的纯粹性)
解决方案 2 :在配置类中定义 @Bean 标识的方法
如果需要定义第三方 Bean 时,通常会单独定义一个配置类
注意事项:
通过 @Bean 注解的 name value 属性可以声明 bean 的名称,如果不指定,默认 bean 的名称
就是方法名。
如果第三方 bean 需要依赖其它 bean 对象,直接在 bean 定义方法中设置形参即可,容器会根
据类型自动装配。
关于 Bean 大家只需要保持一个原则:
如果是在项目当中我们自己定义的类,想将这些类交给 IOC 容器管理,我们直接使用 @Component
以及它的衍生注解来声明就可以。
如果这个类它不是我们自己定义的,而是引入的第三方依赖当中提供的类,而且我们还想将这个类
交给 IOC 容器管理。此时我们就需要在配置类中定义一个方法,在方法上加上一个 @Bean 注解,通
过这种方式来声明第三方的 bean 对象。

2.SpringBoot原理

Spring 是目前世界上最流行的 Java 框架,它可以帮助我们更加快速、更加容易的来构建 Java 项目。而
Spring 家族当中提供了很多优秀的框架,而所有的框架都是基于一个基础框架的
SpringFramework( 也就是 Spring 框架 ) 。而前面我们也提到,如果我们直接基于 Spring 框架进行项
目的开发,会比较繁琐。
这个繁琐主要体现在两个地方:
1. pom.xml中依赖配置比较繁琐,在项目开发时,需要自己去找到对应的依赖,还需要找到依赖
它所配套的依赖以及对应版本,否则就会出现版本冲突问题。
2. 在使用 Spring 框架进行项目开发时,需要在 Spring的配置文件中做大量的配置,这就造成Spring 框架入门难度较大,学习成本较高。
基于 Spring 存在的问题,官方在 Spring 框架 4.0 版本之后,又推出了一个全新的框架:
SpringBoot
通过 SpringBoot 来简化 Spring 框架的开发 ( 是简化不是替代 ) 。我们直接基于 SpringBoot
构建 Java 项目,会让我们的项目开发更加简单,更加快捷。
SpringBoot 框架之所以使用起来更简单更快捷,是因为 SpringBoot 框架底层提供了两个非常重要的
功能:一个是起步依赖,一个是自动配置。
通过 SpringBoot 所提供的起步依赖,就可以大大的简化 pom 文件当中依赖的配置,从而解决了
Spring 框架当中依赖配置繁琐的问题。
通过自动配置的功能就可以大大的简化框架在使用时 bean 的声明以及 bean 的配置。我们只需要引
入程序开发时所需要的起步依赖,项目开发时所用到常见的配置都已经有了,我们直接使用就可以
了。

2.1 起步依赖

假如我们没有使用 SpringBoot ,用的是 Spring 框架进行 web 程序的开发,此时我们就需要引入 web
序开发所需要的一些依赖。
spring-webmvc 依赖:这是 Spring 框架进行 web 程序开发所需要的依赖
servlet-api 依赖: Servlet 基础依赖
jackson-databind 依赖: JSON 处理工具包
如果要使用 AOP ,还需要引入 aop 依赖、 aspect 依赖
项目中所引入的这些依赖,还需要保证版本匹配,否则就可能会出现版本冲突问题。
如果我们使用了 SpringBoot ,就不需要像上面这么繁琐的引入依赖了。我们只需要引入一个依赖就可
以了,那就是 web 开发的起步依赖: springboot-starter-web
为什么我们只需要引入一个 web 开发的起步依赖, web 开发所需要的所有的依赖都有了呢?
因为 Maven 的依赖传递。
SpringBoot 给我们提供的这些起步依赖当中,已提供了当前程序开发所需要的所有的常
见依赖 ( 官网地址: https://docs.spring.io/spring-boot/docs/2.7.7/referen
ce/htmlsingle/#using.build-systems.starters )
比如: springboot-starter-web ,这是 web 开发的起步依赖,在 web 开发的起步依赖当
中,就集成了 web 开发中常见的依赖: json web webmvc tomcat 等。我们只需要引入
这一个起步依赖,其他的依赖都会自动的通过 Maven 的依赖传递进来。
结论:起步依赖的原理就是 Maven 的依赖传递。

2.2 自动配置

我们讲解了 SpringBoot 当中起步依赖的原理,就是 Maven 的依赖传递。接下来我们解析下自动配置的
原理,我们要分析自动配置的原理,首先要知道什么是自动配置。
2.2.1 概述
SpringBoot 的自动配置就是当 Spring 容器启动后,一些配置类、 bean 对象就自动存入到了 IOC 容器
中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。
比如:我们要进行事务管理、要进行 AOP 程序的开发,此时就不需要我们再去手动的声明这些
bean 对象了,我们直接使用就可以从而大大的简化程序的开发,省去了繁琐的配置操作
通过源码的方式去查看自动配置是怎样执行的
大家会看到有两个 CommonConfig ,在第一个 CommonConfig 类中定义了一个 bean 对象, bean 对象的
名字叫 reader
在第二个 CommonConfig 中它的 bean 名字叫 commonConfig ,为什么还会有这样一个 bean 对象呢?原
因是在 CommonConfig 配置类上添加了一个注解 @Configuration ,而 @Configuration 底层就是
@Component
所以配置类最终也是 SpringIOC 容器当中的一个 bean 对象
IOC 容器中除了我们自己定义的 bean 以外,还有很多配置类,这些配置类都是 SpringBoot 在启动的
时候加载进来的配置类。这些配置类加载进来之后,它也会生成很多的 bean 对象。
2.2.1 概述
我们知道了什么是自动配置之后,接下来我们就要来剖析自动配置的原理。解析自动配置的原理就是分
析在 SpringBoot 项目当中,我们引入对应的依赖之后,是如何将依赖 jar 包当中所提供的 bean 以及
配置类直接加载到当前项目的 SpringIOC 容器当中的。
我们就直接通过代码来分析自动配置原理
SpringBoot 项目 spring-boot-web-config2 工程中,通过坐标引入 itheima-utils 依赖
2 、在测试类中,添加测试方法
3 、执行测试方法
异常信息描述:没有 com.example.TokenParse 类型的 bean
说明:在 Spring 容器中没有找到 com.example.TokenParse 类型的 bean 对象
思考:引入进来的第三方依赖当中的 bean 以及配置类为什么没有生效?
因在我们之前讲解IOC的时候有提到过,在类上添加@Component注解来声明bean对象时,还需
要保证@Component注解能被Spring的组件扫描到。
SpringBoot项目中的@SpringBootApplication注解,具有包扫描的作用,但是它只会扫描启
动类所在的当前包以及子包。
当前包:com.itheima,第三方依赖中提供的包:com.example(扫描不到)
那么如何解决以上问题的呢?
方案 1 @ComponentScan 组件扫描
方案 2 @Import 导入(使用 @Import 导入的类会被 Spring 加载到 IOC 容器中)
方案一
@ComponentScan 组件扫描
重新执行测试方法,控制台日志输出:
大家可以想象一下,如果采用以上这种方式来完成自动配置,那我们进行项目开发时,当需要引入
大量的第三方的依赖,就需要在启动类上配置 N 多要扫描的包,这种方式会很繁琐。而且这种大面
积的扫描性能也比较低。
缺点:
1. 使用繁琐
2. 性能低
结论: SpringBoot 中并没有采用以上这种方案。
方案二
@Import 导入
导入形式主要有以下几种:
1. 导入普通类
2. 导入配置类
3. 导入 ImportSelector 接口实现类
1). 使用 @Import 导入普通类:
2). 使用 @Import 导入配置类:
配置类
启动类
测试类
3). 使用 @Import 导入 ImportSelector 接口实现类:
ImportSelector 接口实现类
启动类
4). 使用第三方依赖提供的 @EnableXxxxx 注解
第三方依赖中提供的注解
在使用时只需在启动类上加上 @EnableXxxxx 注解即可
原理分析
2.2.2.1 源码跟踪
前面我们讲解了在项目当中引入第三方依赖之后,如何加载第三方依赖中定义好的 bean 对象以及配置
类,从而完成自动配置操作。那下面我们通过源码跟踪的形式来剖析下 SpringBoot 底层到底是如何完
成自动配置的。
源码跟踪技巧:
在跟踪框架源码的时候,一定要抓住关键点,找到核心流程。一定不要从头到尾一行代码去看,一
个方法的去研究,一定要找到关键流程,抓住关键点,先在宏观上对整个流程或者整个原理有一个
认识,有精力再去研究其中的细节。
要搞清楚 SpringBoot 的自动配置原理,要从 SpringBoot 启动类上使用的核心注解
@SpringBootApplication 开始分析:
我们先来看第一个注解: @SpringBootConfiguration
@SpringBootConfiguration 注解上使用了 @Configuration ,表明 SpringBoot 启动类就是
一个配置类。
@Indexed 注解,是用来加速应用启动的(不用关心)。
接下来再先看 @ComponentScan 注解:
@ComponentScan 注解是用来进行组件扫描的,扫描启动类所在的包及其子包下所有被
@Component 及其衍生注解声明的类。
SpringBoot 启动类,之所以具备扫描包功能,就是因为包含了 @ComponentScan 注解。
最后我们来看看 @EnableAutoConfiguration 注解(自动配置核心注解):
AutoConfigurationImportSelector 类中重写了 ImportSelector 接口的 selectImports()
法:
selectImports() 方法底层调用 getAutoConfigurationEntry() 方法,获取可自动配置的
配置类信息集合
getAutoConfigurationEntry() 方法通过调用
getCandidateConfigurations(annotationMetadata, attributes) 方法获取在配置文
件中配置的所有自动配置类的集合
getCandidateConfigurations 方法的功能:
获取所有基于 META-
INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imp
orts 文件、 META-INF/spring.factories 文件中配置类的集合
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件和 META-INF/spring.factories 文件这两个文件在哪里呢?
通常在引入的起步依赖中,都有包含以上两个文件
第三方依赖中提供的 GsonAutoConfiguration 类:
GsonAutoConfiguration 类上,添加了注解 @AutoConfiguration ,通过查看源码,可以
明确: GsonAutoConfiguration 类是一个配置。
动配置源码小结
自动配置原理源码入口就是@SpringBootApplication注解,在这个注解中封装了3个注解,分别
是:
@SpringBootConfiguration
声明当前类是一个配置类
@ComponentScan
进行组件扫描(SpringBoot中默认扫描的是启动类所在的当前包及其子包)
@EnableAutoConfiguration
封装了@Import注解(Import注解中指定了一个ImportSelector接口的实现类)
在实现类重写的selectImports()方法,读取当前项目下所有依赖jar包中META-
INF/spring.factories、META-
INF/spring/org.springframework.boot.autoconfigure.AutoConfigurat
ion.imports两个文件里面定义的配置类(配置类中定义了@Bean注解标识的方法)。
SpringBoot 程序启动时,就会加载配置文件当中所定义的配置类,并将这些配置类信息 ( 类的全限定
) 封装到 String 类型的数组中,最终通过 @Import 注解将这些配置类全部加载到 Spring IOC 容器
中,交给 IOC 容器管理。
在声明 bean 对象时,上面有加一个以 @Conditional 开头的注解,这种注解的
作用就是按照条件进行装配,只有满足条件之后,才会将 bean 注册到 Spring IOC 容器中(下面
会详细来讲解)
2.2.2.2 @Conditional
我们在跟踪 SpringBoot 自动配置的源码的时候,在自动配置类声明 bean 的时候,除了在方法上加了一
@Bean 注解以外,还会经常用到一个注解,就是以 Conditional 开头的这一类的注解。以
Conditional 开头的这些注解都是条件装配的注解。下面我们就来介绍下条件装配注解。
@Conditional 注解:
作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的 bean 对象到 Spring IOC
器中。
位置:方法、类
@Conditional 本身是一个父注解,派生出大量的子注解:
@ConditionalOnClass :判断环境中有对应字节码文件,才注册 bean IOC 容器。
@ConditionalOnMissingBean :判断环境中没有对应的 bean( 类型或名称 ) ,才注册
bean IOC 容器。
@ConditionalOnProperty :判断配置文件中有对应属性和值,才注册 bean IOC 容器。

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

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

相关文章

[000-002-01].第29节:MySQL数据库缓冲池

1、什么是数据缓冲池&#xff1a; 1.InnoDB 存储引擎是以页为单位来管理存储空间的&#xff0c;我们进行的增删改查操作其实本质上都是在访问页面&#xff08;包括读页面、写页面、创建新页面等操作&#xff09;&#xff0c;而磁盘 I/O 需要消耗的时间很多&#xff0c;而在内存…

电脑如何录屏?无水印、高清晰度电脑录屏教程

现如今&#xff0c;电脑录屏已成为我们工作、学习和娱乐中不可或缺的一部分&#xff0c;日常可以用来录制教学视频、游戏直播、会议记录等等&#xff0c;但有些朋友可能还不知道怎么高清录制视频&#xff0c;今天就给大家带来了几个简单又实用的方法&#xff0c;需要的朋友快码…

Jetpack02-LiveData 数据驱动UI更新(类似EventBus)

前提 LiveData使用了Lifecycle的生命周期&#xff0c;阅读本文前&#xff0c;请先了解Lifecycle源码。 简介 LiveData本质是数据类型&#xff0c;当改变数据的时候&#xff0c;会通知观察者&#xff0c;且只在界面可见的时候才会通知观察者。只能在主线程注册观察者&#xf…

CaLM 因果推理评测体系:如何让大模型更贴近人类认知水平?

CaLM 是什么 CaLM&#xff08;Causal Evaluation of Language Models&#xff0c;以下简称“CaLM”&#xff09;是上海人工智能实验室联合同济大学、上海交通大学、北京大学及商汤科技发布首个大模型因果推理开放评测体系及开放平台。首次从因果推理角度提出评估框架&#xff…

面试经典 150 题:力扣88. 合并两个有序数组

每周一道算法题启动 题目 【题目链接】 【解法一】合并后排序 排序后的数组自动省略0的数字&#xff0c;又学到了 class Solution { public:void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {//合并两个数组后排序for(int i0; i<…

什么人需要远程访问?如何用节点小宝实现远程访问?

随着工作任务日益繁重&#xff0c;远程控制/远程访问成为越来越多人用来提高工作效率的一种方式。远程访问&#xff08;Remote access&#xff09;用来为远程办公人员、外出人员&#xff0c;以及管理多个部门办公室服务器的系统管理员提供远程网络连接。 如何开启远程访问&…

C# winforms 使用菜单和右键菜单

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

C语言课程设计题目一:职工信息管理系统设计

文章目录 题目一&#xff1a;职工信息管理系统设计代码块employeeManagement.hemployeeManage.ctest.c 调试验证录入信息&#xff0c;并浏览验证职工号唯一保存职工信息&#xff0c;加载职工信息按职工号进行查询根据id删除职工修改职工信息 题目一&#xff1a;职工信息管理系统…

国家首次向全社会提供永久基本农田查询服务

自然资源部永久基本农田查询平台正式上线。 据悉&#xff0c;这是国家首次向全社会提供永久基本农田查询服务。 如何查询永久基本农田信息 永久基本农田查询平台正式上线&#xff0c;是对永久基本农田依法实施特殊保护的重要举措&#xff0c;是对各地已开展的永久基本农田公…

分割掩码标注转YOLO多边形标注

Ultralytics 团队付出了巨大的努力&#xff0c;使创建自定义 YOLO 模型变得非常容易。但是&#xff0c;处理大型数据集仍然很痛苦。训练 yolo 分割模型需要数据集具有其特定格式&#xff0c;这可能与你从大型数据集中获得的格式不完全相同。如果你想使用巨大的 OpenImagesV7 作…

MIPI包分析

如下图所示&#xff0c;长方形圈出来的是数据包的规定区域&#xff0c;注意SOT不在packet的定义区间。 分析可知&#xff0c;第一byte就知道包的类型&#xff0c;姑且记作VC2DT6。DT6就是6bits的data type。显而易见总共定义了64中类型&#xff0c;规范中定义了一些&#xff0…

【C++掌中宝】C++ 中的空指针救世主——nullptr

文章目录 1. 什么是 NULL&#xff1f;2. NULL 在 C 和 C 中的区别3. C11 引入 nullptr 的原因4. nullptr 与 NULL 的区别5. nullptr 的应用场景6. 模拟 nullptr 的实现7. 总结结语 1. 什么是 NULL&#xff1f; 在 C 和 C 编程中&#xff0c;NULL 常用于表示空指针&#xff0c;…

展示中国客车硬实力!苏州金龙海格纯电客车惊艳汉诺威商用车展

德国当地时间2024年9月22日&#xff0c;IAA汉诺威商用车展在德国汉诺威展览中心圆满落幕。本届展会&#xff0c;苏州金龙海格客车携新能源公交明星产品Azure7、斯堪尼亚海格高端巴士Fencer F1 Integral EV纯电车型重磅亮相&#xff0c;获得了众多参会嘉宾的好评和关注。来自欧洲…

【活动】人工智能时代,程序员如何保持核心竞争力?需要掌握哪些技能?

人工智能时代&#xff0c;程序员如何保持核心竞争力&#xff1f; 随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;程序员面临着前所未有的挑战和机遇。AI不仅改变了软件开发的方式&#xff0c;也重新定义了程序员的角色。在这种背景下&#xff0c;如何保持…

人工智能助力阿尔茨海默症治疗:微软与上海精神卫生中心的新研究

最近&#xff0c;微软研究院与上海市精神卫生中心合作&#xff0c;基于微软 Azure OpenAI 服务中的多模态大模型&#xff0c;开发了一种名为“忆我”&#xff08;ReMe&#xff09;的个性化认知训练框架。这一创新项目旨在通过数字化手段扩展自动化认知训练的范围&#xff0c;为…

2025考研,报名和初试时间定了!

2025年全国硕士研究生招生初试时间为2024年12月21日至22日&#xff0c;考试时长为6小时的考试科目在12月23日举行。 请考生届时登录“中国研究生招生信息网”&#xff08;网址&#xff1a;https://yz.chsi.com.cn&#xff09;参加报名&#xff0c;查看报名须知、招生单位招生章…

软考高级:云计算架构的五层 AI 解读

云计算架构通常由多个层次构成&#xff0c;每个层次负责不同的功能&#xff0c;协同工作来提供完整的云服务。下面我将详细解释云计算架构的五个主要层次&#xff1a;管理层、用户访问层、应用层、平台层和资源层。 生活化例子 想象一下&#xff0c;云计算架构就像是一座大型…

从金蝶云星空到管易云通过接口配置打通数据

从金蝶云星空到管易云通过接口配置打通数据 接通系统&#xff1a;金蝶云星空 金蝶K/3Cloud结合当今先进管理理论和数十万家国内客户最佳应用实践&#xff0c;面向事业部制、多地点、多工厂等运营协同与管控型企业及集团公司&#xff0c;提供一个通用的ERP服务平台。K/3Cloud支持…

yolov8环境安装

yolov8 git地址 https://github.com/ultralytics/ultralytics/tree/main 我的电脑显卡配置 nvidia-smi cuda11.8下载 https://developer.nvidia.com/cuda-11-8-0-download-archive?target_osWindows&target_archx86_64&target_version10&target_typeexe_local …

保姆级教程!0基础小白也适用,教你用AI美女在小红书“疯狂上分”

文章开始之前&#xff0c;先考考各位小伙伴的眼力&#xff1a;下面的图是真人还是 AI&#xff0c;你能分辨出来吗&#xff1f; 答案是&#xff1a;AI&#xff0c;AI&#xff0c;全是使用stable diffusion生成的AI美女&#xff01; 说实话&#xff0c;最近AI美女是彻底杀疯了&a…