singlleton 的 bean 中注入 prototype 的bean

news/2024/9/28 21:39:31/文章来源:https://www.cnblogs.com/gongchengship/p/18438452

在 Spring 中,prototype Bean 注入 prototype Beansingleton Bean 注入 prototype Bean 是两个典型的场景,尤其在多线程、状态管理等复杂系统中,会有不同的行为和注意事项。

1. prototype Bean 中注入 prototype Bean

当一个 prototype Bean 注入另一个 prototype Bean 时,每次获取外部的 prototype Bean 实例时,Spring 会为该 Bean 创建一个新的实例。这种情况较为简单,因为 prototype 作用域的 Beans 都是动态生成的新实例。

特点:

  • 每个 prototype Bean 都是独立的,每次请求都会创建一个新对象。
  • Spring 管理 Bean 的创建和初始化,但不会管理 prototype Bean 的销毁。

示例:

@Component
@Scope("prototype")
public class PrototypeBeanA {// Prototype Bean A 的逻辑
}@Component
@Scope("prototype")
public class PrototypeBeanB {@Autowiredprivate PrototypeBeanA prototypeBeanA;public void doSomething() {// 每次使用的 prototypeBeanA 都是新的实例System.out.println(prototypeBeanA);}
}

结果:

  • 每次 PrototypeBeanB 被创建时,PrototypeBeanA 也会是一个全新的实例。
  • 因为 PrototypeBeanBprototype 作用域的,所以每次创建 PrototypeBeanB 时,PrototypeBeanA 都会重新注入一个新的实例。

2. singleton Bean 中注入 prototype Bean

这是一个常见的复杂场景,因为 singleton Bean 是单例,而 prototype Bean 是多例。一旦 singleton Bean 被创建,所有的依赖都将固定下来。如果在 singleton Bean 中直接注入 prototype Bean,那么这个 prototype Bean 实际上只会被创建一次,并且在整个应用程序的生命周期中都只会有这个唯一的实例,这显然与 prototype Bean 的设计初衷不符。

特点:

  • 问题:当 singleton Bean 注入 prototype Bean 时,注入的 prototype Bean 只会初始化一次,之后不会再创建新的实例。每次使用的都是同一个 prototype 实例。
  • 解决方法:为了确保 singleton Bean 每次使用 prototype Bean 时都能获取到新的 prototype 实例,必须使用一些特殊的技术,如 @Lookup 方法注入ObjectFactoryProvider

示例 1:直接注入 prototype Bean(错误方式)

@Component
public class SingletonBean {@Autowiredprivate PrototypeBeanA prototypeBeanA;public void doSomething() {// 每次调用时都会使用同一个 prototypeBeanA 实例System.out.println(prototypeBeanA);}
}

在这个例子中,prototypeBeanA 只会被创建一次,因此每次调用 doSomething() 方法时,prototypeBeanA 都是同一个实例,这与 prototype 的预期不一致。

示例 2:使用 @Lookup 方法(正确方式)

@Lookup 注解告诉 Spring 每次调用这个方法时,都需要返回一个新的 prototype 实例。

@Component
public class SingletonBean {@Lookuppublic PrototypeBeanA getPrototypeBeanA() {// Spring 将返回新的 PrototypeBeanA 实例return null; // 这个返回值会被 Spring 动态代理替换}public void doSomething() {PrototypeBeanA prototypeBeanA = getPrototypeBeanA();System.out.println(prototypeBeanA); // 每次获取的都是新的实例}
}

示例 3:使用 ObjectFactory 注入

ObjectFactory 是 Spring 提供的一个工厂接口,用来在每次调用时动态获取 prototype Bean。

@Component
public class SingletonBean {@Autowiredprivate ObjectFactory<PrototypeBeanA> prototypeBeanFactory;public void doSomething() {PrototypeBeanA prototypeBeanA = prototypeBeanFactory.getObject();System.out.println(prototypeBeanA); // 每次获取的都是新的实例}
}

示例 4:使用 Provider 注入

javax.inject.Provider 也提供类似的动态获取 prototype Bean 的功能。

@Component
public class SingletonBean {@Autowiredprivate Provider<PrototypeBeanA> prototypeBeanProvider;public void doSomething() {PrototypeBeanA prototypeBeanA = prototypeBeanProvider.get();System.out.println(prototypeBeanA); // 每次获取的都是新的实例}
}

3. 总结对比

场景 prototype Bean 注入 prototype Bean singleton Bean 注入 prototype Bean
默认行为 每次注入时都会创建新的 prototype 实例 注入的 prototype Bean 只会创建一次(单例生命周期内只创建一次)
常见问题 行为符合预期,每次使用新的 prototype 实例 singleton Bean 会持有同一个 prototype 实例,违背 prototype 设计初衷
解决方案 默认情况下即可实现正确行为 使用 @Lookup 方法、ObjectFactoryProvider 实现动态获取新的 prototype 实例

4. 结论

  • prototype Bean 注入 prototype Bean 时,Spring 的默认行为是符合预期的,每次使用时都会创建新的实例。
  • singleton Bean 需要注入 prototype Bean 时,必须采用 @LookupObjectFactoryProvider 方式来确保每次都能获取新的 prototype 实例,否则默认情况下只会创建一个实例。

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

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

相关文章

星际战甲:战甲配卡

题记部分 一、永恒烈焰(火鸡)进图开2,随后4技能升温、3技能降温,钢铁地图炮 二、标题三、标题— 业精于勤荒于嬉,行成于思毁于随 —

结对项目——四则运算

结对项目——四则运算这个作业属于哪个课程 软工22级计科12班这个作业的要求在哪里 作业要求这个作业的目标 实现四则运算的结对编程项目成员姓名 学号 GitHub链接 分工谭立业 3122004365 github 项目功能的基本实现,博客的编写罗锴佳 3122001905 github 功能函数的测试与完善…

引用拷贝,浅拷贝,深拷贝

参考资料 水平有限,欢迎交流! kimi 【【每天一个技术点】引用拷贝、浅拷贝、深拷贝】 一文搞懂Java引用拷贝、浅拷贝、深拷贝 - bigsai - 博客园 (cnblogs.com) 【黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难】 1. 引用拷贝 (起绰号) 引用拷贝并不是真正意义上…

黑马PM-内容管理-运营管理

消息推送账号管理权限管理日志管理

Blender快速入门教程1简介

0 简介Blender是最著名的 3D 计算机图形制作免费程序之一。有了 Blender,你可以创建角色、道具、环境以及你的想象力所能产生的几乎所有其他东西。它不仅可以创建对象。你还可以让它们运动起来。在动画中讲述一个故事,带领人们穿越你自己创造的世界,或者为一些视频片段添加特…

今天我有博客了!

今天我有博客了!我要把我的编程心得写下来。 今天,我先写了蜗牛打怪兽。我发现需要打的次数都是2^(n)-1,于是我用while循环求出是2的几次方,再用变量一直乘2,最后-1。以下是具体示例。接着,我写了POW。这题限制比较紧,所以不能直接算,得看c是奇数还是偶数:偶数比绝对值…

『模拟赛』csp-s模拟赛6

『模拟赛』csp-s模拟赛6『模拟赛』csp-s模拟赛6 挂分日寄:0+20+0+0 喵喵赛时对拍拍了10000个点都没拍出来,赛后一下就拍出错来了,我谔谔。 T1 DP喵~ 首先 sort 一遍方便处理 其实转移时加一个 abs 取绝对值就可,纯纯多此一举 设 \(f[i,j,1/0]\) 为前 \(i\) 个数中选 \(j\) …

树莓派pico rp2040 使用rust 在ssd1306上显示中文信息

使用u8g2-font + embedded-graphics ,在rp2040 pico上用 ssd1306输出中文信息在rp2040上用DHT22 + ssd1306显示温度信息,用 embedded-graphics库和ssd1306库来实现。但实现的效果不是很理想,无法在ssd1306屏幕上显示中文。为了解决这个问题,在github和crates.io上面找了几天…

typeScript 的第一步---安装

Node.js/浏览器,只认识JS代码,不认识TS代码,需要将TS代码转化为JS代码,然后才能运行。 安装命令:npm i -g typescript 或者 yarn global add typescript 注意:Mac电脑安装全局包时,需要通知添加sudo获取权限。sudo npm i -g typescript 验证安装是否成功:tsc -v 查…

为什么用 AWS CLI?因为我懒得点鼠标!

在这篇博客中,我们一起深入探索 AWS CLI 的世界,从零开始,逐步构建在云端的家园。将介绍 AWS CLI 的基本功能和使用场景,如何创建 IAM 用户、VPC、子网、安全组、EC2 实例等,甚至还会搭建一个应用负载均衡器(ALB)。无论你是初学者还是有一定基础的用户,都能通过本指南掌…

妙用编辑器:使用Notepad--正则表达式从命令结果报文快速生成新命令

应用场景 日常生活中有些维护场景,比如检查设备状态,执行查询命令后,得到精简结果报文,如果要更深入的检查状态,可能还要执行其他命令,逐个对象进行查询,这里涉及到快速从报文生成查询指令的功能。 比如有如下一个从LST 命令查询出来的报文,需要快速的生成DSP命令,逐个…