Spring之Bean详解

news2025/1/18 20:07:23

Spring之Bean详解

什么是Bean?

在Spring中,Bean是指由Spring容器管理的对象,这些对象是由Spring IoC容器负责创建、组装和管理的。Bean可以是Java类的实例,也可以是其他Spring管理的组件,例如数据源、事务管理器等。

怎么声明一个Bean?

Bean的声明可以通过注解或者XML文件进行配置,这里主要使用现在流行的注解模式进行讲解

通过类声明Bean

在Bean对象对应的类上添加@Component 、@Repository 、@Service、@Controller中的任意一个注解,但是要注意这几个注解一般是为了让开发人员识别Bean对象的作用,比如@Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。

通过@Bean声明Bean
@Configuration
public class RedisTemplateConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setKeySerializer(RedisSerializer.string());
        return redisTemplate;
    }
}
怎么样注入Bean对象?

常见的注入方式有@AutoWired和@Resource这两个注解

@Component
public class AnalysisController {

    @Resource
    private Service service1;
  
  	@Autowired
    private Service service2;
  
}
@AutoWired和@Resource区别

Autowired 属于 Spring 内置的注解,默认的注入方式为byType(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。

这会有什么问题呢? 当一个接口存在多个实现类的话,byType这种方式就无法正确注入对象了,因为这个时候 Spring 会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。

例如:现在容器中有两个Bean [<serviceImpl1, Service>, <serviceImpl2, Service>], @Autowired会先根据Service类型找对应的Bean,找到了名为serviceImpl1、serviceImpl2这两个Bean,然后byName,看是否有对应的名为service1的Bean,发现都没有,报错

区别

ResourceAutowired相反,它是先byName找,如果没找到,再byType

Bean的作用域
  1. 单例(Singleton):最常用的作用域,也是Spring默认的作用域
    • 说明: 默认作用域,一个容器中只存在一个Bean实例。
    • 生命周期: 在容器启动时创建,直到容器关闭时销毁。
    • 应用场景: 适用于无状态的、共享的Bean,例如服务层组件。
@Scope("singleton")
public class MySingletonBean {
    // ...
}
  1. 原型(Prototype):
  • 说明: 每次请求都会创建一个新的Bean实例。
  • 生命周期: 在每次请求时创建,使用后不受容器管理,由Java垃圾回收机制负责销毁。
  • 应用场景: 适用于有状态的、独立的Bean,例如控制器、工具类等。
@Scope("prototype")
public class MyPrototypeBean {
    // ...
}
  1. 会话(Session):
  • 说明: 在Web应用中,每个会话都会创建一个Bean实例。
  • 生命周期: 在会话创建时创建,会话销毁时销毁。
  • 应用场景: 主要用于Web应用中的会话管理,例如保存用户的登录状态。
@Scope("session")
public class MySessionBean {
    // ...
}
  1. 请求(Request):
  • 说明: 在Web应用中,每个请求都会创建一个Bean实例。
  • 生命周期: 在每次HTTP请求时创建,请求结束时销毁。
  • 应用场景: 主要用于Web应用中的请求处理,例如保存用户请求的临时数据。
@Scope("request")
public class MyRequestBean {
    // ...
}
  1. 全局会话(Global Session):
  • 说明: 仅在Web应用中有效,全局会话是一组会话的抽象,由Servlet容器管理。
  • 生命周期: 在全局会话创建时创建,全局会话销毁时销毁。
  • 应用场景: 主要用于Portlet应用中,用于跨多个会话的共享Bean。
@Scope("globalSession")
public class MyGlobalSessionBean {
    // ...
}

选择适当的作用域取决于应用的需求,通过合理配置作用域可以提高应用性能、降低资源消耗,并更好地管理Bean的生命周期。

Bean的线程安全问题

在Spring中,Bean的线程安全问题主要涉及到在多线程环境下共享的Bean实例。Spring默认情况下,Bean是单例的,即在整个应用中只有一个实例。在多线程环境下,如果多个线程同时访问和修改这个单例Bean,就可能引发线程安全问题。

我们这里以最常用的两种作用域 prototype 和 singleton 为例介绍。几乎所有场景的 Bean 作用域都是使用默认的 singleton ,重点关注 singleton 作用域即可。

prototype 作用域下,每次获取都会创建一个新的 bean 实例,不存在资源竞争问题,所以不存在线程安全问题。singleton 作用域下,IoC 容器中只有唯一的 bean 实例,可能会存在资源竞争问题(取决于 Bean 是否有状态)。如果这个 bean 是有状态的话,那就存在线程安全问题(有状态 Bean 是指包含可变的成员变量的对象)。

不过,大部分 Bean 实际都是无状态(没有定义可变的成员变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。

对于有状态单例 Bean 的线程安全问题,常见的有两种解决办法:

  1. 在 Bean 中尽量避免定义可变的成员变量。
  2. 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。

Bean的生命周期

在Spring框架中,Bean的生命周期是管理和控制对象创建、初始化、使用和销毁的全过程。理解和掌握Bean的生命周期对于使用Spring框架开发应用程序是非常重要的一部分。

Bean的生命周期管理是为了确保在对象创建、初始化、使用和销毁的过程中,Spring容器能够正确地执行各种任务,如依赖注入、初始化方法、销毁方法等。通过Bean的生命周期管理,Spring可以更好地控制对象的行为,提高系统的可维护性和灵活性。

Bean的生命周期包括以下阶段:

Spring Bean 生命周期

  1. 实例化(Instantiation): Spring容器根据配置文件或注解等信息,实例化Bean对象。这一阶段涉及到类的加载和实例化过程。
  2. 属性赋值(Populate Properties): Spring容器为Bean注入属性值,包括基本数据类型、引用类型等。这一阶段涉及到依赖注入。
  3. 初始化前(Initialization): 在调用Bean的初始化方法之前,Spring容器可以允许用户自定义一些初始化操作。这一阶段涉及到InitializingBean接口、@PostConstruct注解等。
  4. 初始化(Initialization): 调用Bean的初始化方法,完成Bean的初始化。这一阶段涉及到init-method配置、@PostConstruct注解等。
  5. 初始化后(Initialization): 在调用Bean的初始化方法之后,Spring容器可以允许用户自定义一些初始化操作。这一阶段涉及到InitializingBean接口、@PostConstruct注解等。
  6. 使用中(In Use): Bean对象被正常使用,处于活动状态。
  7. 销毁前(Destruction): 在调用Bean的销毁方法之前,Spring容器可以允许用户自定义一些销毁操作。这一阶段涉及到DisposableBean接口、@PreDestroy注解等。
  8. 销毁(Destruction): 调用Bean的销毁方法,完成Bean的销毁。这一阶段涉及到destroy-method配置、@PreDestroy注解等。

总结

Bean的生命周期是Spring框架的一个重要概念,通过生命周期管理,Spring容器能够更好地控制对象的创建、初始化、使用和销毁过程。理解Bean的生命周期有助于开发者更好地利用Spring框架的特性,编写出高质量、易维护的应用程序。在实际应用中,可以通过实现特定接口、配置初始化和销毁方法、使用注解等方式来定制Bean的生命周期。

如果觉得本篇文章对于你理解Spring的Bean有帮助,可否点个小赞😺;篇幅较长建议收藏🫠;关注一手等待后续更新更多干货🚀

参考链接:https://javaguide.cn/system-design/framework/spring/spring-knowledge-and-questions-summary.html

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

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

相关文章

深空通信DTN总结

这里写自定义目录标题 A novel Federated Computation approach for Artificial Intelligence applications in Delay and Disruption Tolerant NetworksabstractintroductionDELAY AND DISRUPTION TOLERANT NETWORKS联邦计算用于容忍延迟和干扰的网络的联合学习框架DTN-ML Orc…

MySQL 学习笔记(基础篇 Day2)

「写在前面」 本文为黑马程序员 MySQL 教程的学习笔记。本着自己学习、分享他人的态度&#xff0c;分享学习笔记&#xff0c;希望能对大家有所帮助。推荐先按顺序阅读往期内容&#xff1a; 1. MySQL 学习笔记&#xff08;基础篇 Day1&#xff09; 目录 3 函数 3.1 字符串函数 3…

关于springboot一个接口请求后,主动取消后,后端是否还在跑

1、最近在思考一个问题&#xff0c;如果一个springboot的请求的接口比较耗时&#xff0c;中途中断该请求后&#xff0c;则后端服务是否会终止该线程的处理&#xff0c;于是写了一个demo RequestMapping(value "/test", method RequestMethod.GET)public BasicResul…

响应人大代表王旭的提议:996程序员也要每天一节体育课

哈喽&#xff0c;我是熊子峰&#xff0c;38岁程序员&#xff0c;正在结合AI写作进行自我成长&#xff0c;穿越程序员的中年危机&#xff0c;这是第 69 篇日更文章。 每天一节体育课 今天&#xff0c;看到一条新闻&#xff0c;人大代表王旭提议中小学生每天应该有一节体育课&am…

docker安装和使用kafka

1. 启动zookeeper Kafka依赖zookeeper, 首先安装zookeeper -p&#xff1a;设置映射端口&#xff08;默认2181&#xff09; docker run --name zookeeper \--network app-tier \-e ALLOW_ANONYMOUS_LOGINyes \--restartalways \-d bitnami/zookeeper:latest2. 启动kafka docker…

Vscode 使用SSH远程连接树莓派的教程(解决卡在Downloading with wget)

配置Vscode Remote SSH 安装OpenSSH 打开Windows开始页面&#xff0c;直接进行搜索PowerShell&#xff0c;打开第一个Windows PowerShell&#xff0c;点击以管理员身份运行 输入指令 Get-WindowsCapability -Online | ? Name -like OpenSSH* 我是已经安装好了&#xff0c;…

基于springboot的车辆充电桩管理系统(系统+数据库+文档)

** &#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;** 一、研究背景…

彻底搞清楚CUDA和cuDNN版本问题

彻底搞清楚CUDA和cuDNN版本问题 1. 缘起 我的机器上以下三条指令输出的版本不相同。 nvcc -V # 这个输出11.7 nvidia-smi # 右上角显示12.3 import torch; torch.version.cuda # 这个输出12.1我想以此为契机&#xff0c;彻底搞清楚CUDA、cuDNN和torch之间的关系。 环境&a…

Wireshark——获取捕获流量的前N个数据包

1、问题 使用Wireshark捕获了大量的消息&#xff0c;但是只想要前面一部分。 2、方法 使用Wireshark捕获了近18w条消息&#xff0c;但只需要前5w条。 选择文件&#xff0c;导出特定分组。 输入需要保存的消息范围。如&#xff1a;1-50000。 保存即可。

阿里云2核4G服务器支持人数并发测试,2核4G主机测评

阿里云2核4G服务器多少钱一年&#xff1f;2核4G配置1个月多少钱&#xff1f;2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年。可以在阿里云CLUB中心查看 aliyun.club 当前最新2核4G服务器精准报价、优惠券和活动信息。 阿里云官方2…

Docker部署ruoyi前后端分离项目

目录 一. 介绍前后端项目 二. 搭建局域网 2.1 创建网络 2.2 注意点 三. Redis 3.1 安装 3.2 配置redis.conf文件 3.3 测试 四. 安装MySQL 4.1 安装 4.2 配置my2.cnf文件 4.3 充许远程连接 五. 若依部署后端服务 5.1 数据导入 5.2 使用Dockerfile自定义镜像 5.3 运行…

青少年如何从零开始学习Python编程?有它就够了!

文章目录 写在前面青少年为什么要学习编程 推荐图书图书特色内容简介 推荐理由粉丝福利写在最后 写在前面 本期博主给大家带来一本非常适合青少年学习编程的图书&#xff0c;快来看看吧~ 青少年为什么要学习编程 青少年学习编程&#xff0c;就好比在他们年轻时就开始掌握一种…

[C语言]——分支和循环(2)

目录 一.逻辑操作符&#xff1a;&& , || , &#xff01; 1.逻辑取反运算符! 2.与运算符&& 3.或运算符 4.练习&#xff1a;闰年的判断 5.短路 二.switch语句 1.if语句和switch语句的对比 2.switch语句中的break 3.switch语句中的default 4.switch…

docker 数据卷 详解与实践

常见的数据卷命令 命令 说明 文档地址 docker volume create 创建数据卷 docker volume create docker volume ls 查看所有数据卷 docs.docker.com docker volume rm 删除指定数据卷 docs.docker.com docker volume inspect 查看某个数据卷的详情 docs.docker.co…

MIT 6.S081---Lab: Multithreading

Uthread: switching between threads (moderate) 修改uthread.c&#xff0c;在thread中新增context字段&#xff1a; 修改uthread.c&#xff0c;在thread_create函数中新增以下逻辑&#xff1a; 修改uthread.c中的thread_switch函数定义&#xff1a; 修改uthread.c中的th…

代码随想录算法训练营第三十八天|509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

509. 斐波那契数 刷题https://leetcode.cn/problems/fibonacci-number/description/文章讲解https://programmercarl.com/0509.%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE视频讲解https://www.bilibili.com/video/BV…

框架漏洞--->Log4j2 Shiro1.2.4反序列化基础

上次讲了thinkphp 那么这次我们就来讲一下log4j2 1.关于log4j2的原理 ----> CVE-2021-44228 当时这个漏洞出来的时候&#xff0c;可以说是轰动了全球~!!!!! 当时基本上是用这个框架的都爆出了这个漏洞 于是&#xff0c;它就在框架漏洞中占有了一席重要之地&#xff01;&am…

【C语言 数据结构】堆与二叉树(下)

接着上次的&#xff0c;这里主要介绍的是堆排序&#xff0c;二叉树的遍历&#xff0c;以及之前讲题时答应过的简单二叉树问题求解 堆排序 给一组数据&#xff0c;升序&#xff08;降序&#xff09;排列 思路 思考&#xff1a;如果排列升序&#xff0c;我们应该建什么堆&#x…

Redis面试题(答案版)2024

基础内容 1、简单介绍以下你了解的Redis &#xff08;1&#xff09;高性能&#xff1a;Redis是基于内存的&#xff0c;读写速度非常快&#xff0c;可以支持10w的QPS。 &#xff08;2&#xff09;用途多样&#xff1a;缓存、消息队列、分布式锁等 &#xff08;3&#xff09;支持…

物联网电气融合实训室建设方案

1 教学实训总体设计 1.1 建设背景 &#xff08;一&#xff09;政策推动与战略部署 近年来&#xff0c;物联网技术在全球范围内得到了广泛的关注和应用。作为信息技术的重要组成部分&#xff0c;物联网在推动经济转型升级、提升社会管理水平、改善民生福祉等方面发挥着重要作…