【SpringBoot】Bean 是什么?

感兴趣的话,可以看我另外一篇关于 Bean 的文章:【Java基础】Spring 中 Bean 的理解与使用

一、Bean 定义

Bean 作为 Spring 框架面试中不可或缺的概念,其本质上是指代任何被 Spring 加载生成出来的对象。(本质上区别于 Java Bean,Java Bean 是对于 Java 类的一种规范定义。)Spring Bean 代表着 Spring 中最小的执行单位,其加载、作用域、生命周期的管理都由 Spring 操作。可见 Spring Bean 在整个 Spring 框架中的重要地位。

二、设计目的

在了解 Spring 是如何管理 Bean 组件之前,咋们有必要了解为什么 Spring 需要设计出来这么一套机制。假设当前咋们是某个大家族里的公子转世,天天过着衣来伸手饭来张口的生活。在你的家里有一位无微不至的大管家,无论你需要什么,只要跟管家说一下,他就能给你找来。

有一天,你突然饿了,于是你对着管家吩咐道:“本少爷想吃帝王蟹。”。管家听到命令后,吭哧吭哧的给你搞来了。至于管家到底是抓来的、还是买来的,作为少爷的你自然是不关注的。

与此相类似的,如果把程序员想象成少爷,那么 SpringBoot 就是我们忠诚的管家先生。当我们需要用容器内的对象时,只需要“告诉” Spring,Spring 就能自动帮我们加载,我们则无需考虑这个 Bean 到底是如何加载的、什么时候回收等细节逻辑。我们只需要使用即可。由此一来,降低了使用门槛,也减少了对于细节的一些管理。

三、名词介绍

  1. 定义Bean 是在 Spring 容器中被实例化、管理和维护的对象一个 Bean 可以是任何普通的 Java 对象,例如 POJO、Service、Respository、Controller 等等。将一个类声明为 Bean 的方式可以是在类级别上使用 ‘@Component’ 注解或其派生注解(‘@Service’、‘@Repository’、‘@Controller’等),也可以是通过配置文件进行显式的声明。
  2. 实例化:Spring 容器负责实例化 Bean。当应用程序启动时,Spring 容器会根据配置信息或注解扫描的结果,找到并实例化所有被标记为 Bean 的类,并将它们加入容器中。实例化的过程由 Spring 的 IoC 容器负责。
  3. 管理一旦 Bean 被实例化,Spring 容器将负责管理 Bean 的生命周期和依赖关系。它会根据配置文件或注解的信息,自动解决 Bean 之间的依赖关系,确保在需要的时候正确的注入依赖。Spring 容器还会负责销毁不再需要的 Bean。
  4. 依赖注入依赖注入是 Spring 框架的一个重要特性,它允许通过自动或显式配置的方式将 Bean 的依赖项注入到其它 Bean 中依赖注入可以通过构造函数注入、Setter 方法注入或字段注入的方式实现,其中最常见的是使用 ‘@Autowired’注解进行注入
  5. 作用域Spring 框架提供了多种作用域(scope)来管理 Bean 的生命周期。常见的作用域包括单例(Singleton)、原型(Prototype)、会话(Session)、请求(Request)等。默认情况下,Bean 是单例的,即每个容器中只存在一个实例。但可以根据需要配置其它作用域
    @Component // 默认为单例
    public class MyBean {
        // 代码...
    }
    
    -------------------------------------
    
    @Component
    @Scope("prototype")
    public class MyPrototypeBean {
        // 代码...
    }
  6. 自动装配Spring Boot 支持自动装配(Auto - wiring),它能够根据类型或名称自动解析和注入依赖关系。通过在需要注入的字段、构造函数或 Setter 方法上使用 ‘@Autowired’ 注解,Spring 容器会自动查找并注入对应的 Bean
    @Component
    public class MyService {
        @Autowired
        private MyBean myBean;
        
        // 使用myBean的代码...
    }

    总的来说,Bean 是 Spring 框架中被实例化、管理和维护的对象。通过在类上使用 ‘@Component’ 注解或其派生注解,将一个类声明为 Bean,并将其交给 Spring 容器处理。Spring 容器负责实例化、管理和维护 Bean 的生命周期和依赖关系。通过依赖注入和自动装配,应用程序可以方便的使用和管理 Bean

 四、装配及注入

在了解了 Spring 设计 Bean 的目的以后,我们就可以来了解下在 Spring 中,我们是如何告诉 Spring,我们需要一个 Bean 的了。以下面的 MyBean 类为例子,我们来一步步介绍 Spring 是如何管理、加载 bean 的。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyBean {
    Integer filedA;

    Integer fieldB;
}

开门见山的说,Spring 对于 Bean 的装配有三种方式:xml 装配、Java 显式配置和自动装配

xml 装配

xml装配就不介绍了,因为是比较老的装配方式了

Java 装配

经常在第三方项目中,如果我们想要注入一个容器,那么往往需要通过注解 @Configuration + @Bean 的方式进行实现。如下所示:

@Configuration
public class MyBeanConfiguration {

    @Bean(name = "myBean")
    public MyBean initMyBean() {
        return new MyBean();
    }

}

-------------------------------------------------

@SpringBootApplication
@ComponentScan(basePackages = {"com.example.demo.*", "com.alibaba"}) // 需指明路径。
public class emptyDemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(emptyDemoApplication.class, args);

        Object myBean = context.getBean("myBean");
        System.out.println(myBean); // MyBean(filedA=null, fieldB=null)
    }

}

需要注意的点是,Spring 默认是不会开启第三方的 bean 扫描的(这个取决于下面一种的自动装配机制。),如果需要对第三方的包进行扫描,那么需要采用 @ComponentScan 注解进行显式的指明。

自动装配

自动装配机制是 SpringBoot 的一大亮点之一,其主要依赖于 @SpringBootApplication 下的 @EnableAutoConfiguration 注解该注解在 @SpringBootApplication 注解里面,看源码可以看到)实现。简单来说,就是在该注解指定的目录下,通过使用 @Component 及其衍生注解如 @Service、@Repository 等,Spring 就会默认将对应对象注册到容器中。具体例子如下:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class MyBean {

    Integer filedA;

    Integer fieldB;

}

-------------------------------------------------

@SpringBootApplication
@ComponentScan(basePackages = {"com.example.demo.*", "com.alibaba"}) // 需指明路径。
public class emptyDemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(emptyDemoApplication.class, args);

        Object myBean = context.getBean("myBean");
        System.out.println(myBean); // MyBean(filedA=null, fieldB=null)
    }

}

 自动装配的方案,遵循了“约定大于配置”的设计理念,通过约定俗成来极大减少了程序员开发的成本。在通常情况下,Spring 只会默认扫描当前类路径下的组件,不会扫描其它第三方包组件。可以通过上文的 @ComponentScan 来扩充扫描的范围。

五、生命周期

作用域

在了解了 Bean 的设计目的及其装配注入的方式后,咋们有必要对 Bean 的整个生命周期做一个了解。但是在了解具体的生命周期之前,我们需要了解一个概念,即容器的作用域。作用域大致有以下五种:

作用域含义
singleton(默认)将单个 bean 定义限定为每个 Spring IoC 容器的单个对象实例。
prototype将单个 bean 定义限定为任意数量的对象实例
request每次用户请求时,只生成一个 Bean 对象
session每次 Http 会话建立到终止时,只能够生成一个对应的 Bean 实例
application每次应用启动到终止,只维持一个对应的 Bean 实例对象
  1. websocket
每次 webSocket 从建立链接到断开链接,只存在一个对应的 Bean 实例对象

从含义的解释上来看,作用域主要是解决 Bean 的作用范围的。以 singleton 和 prototype 来说,singleton 在创建之后,springboot 会保证整个上下文环境中都只存在一个该类型的 bean。而如果是 prototype 情况,那么每次 springboot 发生加载的时候,都会新创建一个 bean 进行注入。

相似的,request、session则是在每次用户请求、每次会话建立都新创建 bean 进行注入。通过指定作用域,我们就可以判断出当前这个 Bean 对象的大致生命周期和作用范围。

Bean 生命周期

从主观上来考虑,一个 Bean 在容器中管理,大概需要以下这么几步:

  1. 调用构造方法,创建对应的 Bean 类。此时 Bean 类中的属性都是空的。
  2. 将 Bean 所依赖的一些数据,如待注入的容器等,填充到 Bean 对象中。
  3. 调用 bean 内的一些方法,如启动数据库链接等。同时将 Bean 填充到容器中存储起来,以方便应用程序获取使用。
  4. 如果当前不再使用该 Bean 对象,则调用销毁方法,将当前 Bean 销毁。

而这上述几步,其实也就对应着 Bean 生命周期:

  • 实例化 Instantiation(指创建对象的过程,也就是说,当 Spring 容器启动时,它会扫描所有的配置文件,读取 Bean 定义,然后根据定义创建 Bean 对象的实例。这个过程中,Spring 容器会使用反射机制来调用 Bean 的构造函数来实例化对象。
  • 属性赋值 Populate
  • 初始化 Initialization(指 Bean 对象被创建后,Spring 容器会根据配置文件中的定义来对其进行一系列的属性设置、依赖注入等操作,使其可以正常运行。这个过程中,Spring 容器会调用 Bean 的一些特定方法,如 set 方法、init-method 方法等来完成对象的初始化。)
  • 销毁 Destruction

实例化和初始化的区别:实例化是创建对象的过程,而初始化是为对象设置属性、注入依赖以及调用特定方法来使其准备好执行操作的过程。在 Spring 框架中,实例化和初始化都是由容器来管理的,可以通过配置文件或者注解来指定 Bean 的创建和初始化过程。

同时,为了方便拓展,Spring 也在特定的生命周期前后提供了接口以供拓展实现,最重要的两个实现接口就是如下两个:

  • InstantiationAwareBeanPostProcessor
  • BeanPostProcessor

InstantiationAwareBeanPostProcessor 主要在 Bean 实例化、属性赋值的时候提供了拓展接口;

而 BeanPostProcessor 则主要在 Bean 初始化前后提供拓展接口。我们熟知的 @PostConstruct 注解,就是通过实现了 BeanPostProcessor 接口,来实现的后处理机制。

总体来说,Spring 中 bean 的基本生命流程主要如下所示:

六、参考文档

  • 如何理解Spring中的Bean
  • 【SpringBoot】详细介绍SpringBoot中的bean

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

迪文串口屏屏幕界面制作软件T5L_DGUS Tool\\DGUS_V7647的使用

一、概述 使用迪文串口屏要首先用屏幕界面制作软件T5L_DGUS Tool制作界面,然后在直面上设置变量,变量对应有地址。单片机可以使用串口发送数组,数组为迪文屏的控制指令,比如写数据指令,该指令中有变量的地址&#xff0…

k8s创建资源对象过程

我们都知道,K8S中一切皆资源,在使用K8S时,所有的pod或者controller都是通过yaml文件进行创建的。 那么接下来,就和大家一起看一下K8S是如何创建资源的。 创建资源对象的过程 Deployment是一种常见的资源对象。在Kubernetes系统…

低代码-详情页组件设计

效果图 详情页数据结构定义 layout:{// 按钮数据buttonLayout:{headButton:[], // 页头按钮footButton:[] // 页脚按钮},// 详情页表单配置config:{}, // 配置组件列表detailLayout:[]}默认行为 进表单初始化,只展示表单属性,隐藏通用、数据、事件tab项…

springboot第50集:File类,IO流,网络编程,反射机制周刊

image.png FileReader、FileWriter的使用 FileInputStream、FileOutputStream的使用 image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png 服务器内存优化是一个复杂的过程,通常需要综合考虑…

存储系统——Ceph

目录 存储基础 单机存储设备 单机存储的问题 分布式存储(软件定义的存储 SDS) 分布式存储的类型 Ceph 概述 Ceph 优势 Ceph 架构 RADOS 基础存储系统 LIBRADOS 基础库 高层应用接口 应用层 Ceph 核心组件 OSD(Object Storage D…

实现歌词滚动效果

文章目录 需求源码 需求 有一段音频和一个字符串格式的歌词&#xff0c;现欲将二者结合做到歌词随音乐播放歌词滚动的效果&#xff0c;如下图所示 源码 目录结构 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&…

windows PyCharm远程同步Linux服务器上的项目文件,以及远程连接Linux服务器上的python环境

&#xff08;1&#xff09;上传项目文件到Linux服务器和前置说明 &#xff08;1-1&#xff09;本地项目文件地址&#xff1a;D:\Python_Work\XXX &#xff08;1-2&#xff09;阿里云服务器项目文件地址&#xff1a;/home/XXX &#xff08;1-3&#xff09;Pycharm必须是专业版…

杨中科 .NETCORE EFCORE第七部分 一对一,多对多

一对一 一对一关系配置 1、builder.HasOne(o >o.Delivery).WithOne(d>d.Order).HasForeignKey(d>dOrderId); 2、测试插入和获取数据 示例 新建 Order 新建 Delivery DeliveryConfig OrderConfig 执行 迁移命令 查看数据库 测试数据插入 运行查看数据 多对多…

Qt中ComboBox的简单使用

1.相关说明 combobox中item的文字、data、图片设置 2.界面绘制 3.相关主要代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete …

怎么修改或移除WordPress后台仪表盘概览底部的版权信息和主题信息?

前面跟大家分享『WordPress怎么把后台左上角的logo和评论图标移除&#xff1f;』和『WordPress后台底部版权信息“感谢使用 WordPress 进行创作”和版本号怎么修改或删除&#xff1f;』&#xff0c;其实在WordPress后台仪表盘的“概览”底部还有一个WordPress版权信息和所使用的…

【Python笔记】pip intall -e命令:让你的工程直接使用开源包的源码,可断点调试,修改源码!

最近学习MetaGPT&#xff0c;用到了 pip install -e . 安装命令&#xff0c;这个安装命令是从源代码安装包。 从源代码安装包有几个好处&#xff1a; 包内的代码是可见的&#xff0c;是白盒&#xff0c;不是黑盒&#xff0c;可以直接在项目中看源码断点调试可以直接断到源码里…

看看通义天问AI的水平怎么样?

写在前面 我问了通义千问一个问题&#xff1a;gooey项目改名后的新名字是什么&#xff1f; 这个问题很模糊&#xff0c;它把gooey理解为一个python库&#xff0c;这很正常&#xff0c;毕竟该项目知名度大。 随着对话的进展&#xff0c;我补充了相关信息&#xff0c;将上下文领…

QT软件在线安装与维护

一.安装 安装QT开发环境分离线安装和在线安装两种方式&#xff0c;具体步骤如下&#xff1a; QT官网注册账号----下载安装包-----安装-----选择要安装的版本与开发包----版本维护 注意&#xff1a;Qt5.14.2是最后提供二进制安装包的版本&#xff0c;后面的版本都需要在线安装…

力扣hot100 爬楼梯 线性DP

Problem: 70. 爬楼梯 复杂度 时间复杂度: O ( n ) O(n) O(n) Code class Solution {public int climbStairs(int n){int[] f new int[n 1];f[0] 1;f[1] 1;for (int i 2; i < n; i)f[i] f[i - 1] f[i - 2];return f[n];} }

保证Kafka消息有序性

一、Kafka特性 写入同一个partion分区中的数据是一定有顺序的kafka中一个消费者消费一个partion的数据&#xff0c;消费者取出数据时&#xff0c;也是有顺序的 二、保证消息Kafka消息有序性 在生产者端&#xff0c;应保证消息被写入同一分区。可以在构造消息时指定消息的key…

【技术科普】四大主流芯片架构及其主要优势!

在“算力时代”&#xff0c;数字经济蓬勃发展下数据量呈现爆发式增长&#xff0c;数据价值凸显&#xff0c;从数据的产生到数据的传输、再到计算、处理&#xff0c;都离不开计算芯片&#xff0c;影响着计算芯片的芯片架构到底是什么&#xff1f;有什么作用&#xff1f;今天我们…

Springboot使用参数解析器HandlerMethodArgumentResolver,解析请求头里的数据

HandlerMethodArgumentResolver 是 Spring MVC 中的一个接口&#xff0c;它允许你自定义方法参数的解析过程。当处理请求时&#xff0c;Spring MVC 需要将请求中的信息映射到控制器方法的参数上&#xff0c;而 HandlerMethodArgumentResolver 允许你在这个过程中进行自定义操作…

群晖搭建LDAP服务器实现一个账号登录DSM、Gitea、jellyfin

文章目录 前言安装LDAP Server新建群组新增用户 DSM加入LDAPDSM使用LDAP登录 Gitea配置登录取消其登录权限 Jellyfin配置登录 总结 前言 LDAP&#xff08;轻量级目录访问协议&#xff09;是一种用于访问和管理分布式目录服务的协议&#xff0c;它具有以下好处&#xff1a; 集…

【USTC】verilog 习题练习1-5

1 编写 Verilog 代码&#xff0c;使电路输出信号1 输入格式 无输入 输出格式 输出1&#xff0c;位宽为1 module top_module(output out );// Write your code hereassign out 1; endmodule 2编写 Verilog 代码&#xff0c;使电路输出信号0 输入格式 无输入 输出格式 …

虚拟ip可以解决所有的安全问题吗

虚拟IP&#xff08;Virtual IP&#xff09;是一种网络技术&#xff0c;可以把多台物理服务器或设备组合成一个逻辑集群&#xff0c;并且使用同一个IP地址对外提供服务。虚拟IP具有负载均衡、故障切换和高可用性等优势&#xff0c;同时还可以作为一种安全措施来增加系统的抗攻击…