前言:之前看到Spring中一个有趣的、但值得注意的问题,就是Spring中关于如何协调Bean作用域不同步?正常来讲,两个singleton作用域的bean存在依赖关系时,或者当prototype作用域的bean依赖singleton作用域的bean时,使用Spring默认提供的依赖注入管理即可,但是如果出现这种情况:singleton作用域的Bean依赖prototype作用域Bean时,会出现使用单例Bean时,每次其依赖的多例Bean都是同一个,这与多例Bean的设计初衷相违背。
本篇文章只关注以下问题:
- 如何将多例Bean正确注入单例Bean中
1. 问题描述
singleton作用域的Bean只有一次实例化机会,它的依赖关系也只在初始化阶段被设置,当singleton作用域的Bean依赖prototype作用域的Bean时,Spring容器会在初始化singleton作用域的Bean之前,先创建被依赖的prototype Bean,然后才初始化singleton Bean,并将prototype Bean注入到singleton Bean,这会导致以后无论何时通过singleton Bean去访问prototype Bean时,得到的永远是最初那个prototype Bean——这就相当于singleton Bean把它所依赖的prototype Bean变成了singleton行为。
由上产生出问题:如果客户端通过singleton Bean去调用prototype Bean的方法时,始终都是调用同一个prototype Bean实例,这就违背了设置prototype Bean的初衷——本来希望它具有prototype行为,但实际上它却表现出了singleton行为。
2. 解决思路
- 放弃依赖注入:singleton作用域的Bean每次需要prototype作用域的Bean时,主动向容器请求新的Bean实例,即可保证每次注入的prototype Bean实例都是最新的;
- 利用Spring提供的方法注入
第一种方式实际上是放弃Spring带来的控制反转的优势,代码主动请求新的Bean实例,必然导致程序代码与SpringAPI耦合,造成代码污染。
方法注入通常使用lookup方法注入,使用lookup方法注入可以让Spring容器重写容器中Bean的抽象或具体方法,返回查找容器中其他Bean的结果,被查找的Bean通常是一个not-singleton Bean。Spring通过使用JDK动态代理或cglib库修改客户端的二进制代码,从而达到上述要求。
3. Demo输出
假设有一个Chinese类型的Bean,该Bean包含一个signName()方法,执行该方法时需要依赖于Pen的方法——而且程序希望每次执行signName()方法时都使用不同的Pen Bean,因此首先需要将Pen Bean设置为prototype作用域。
除此之外,不能直接使用普通依赖注入将Pen Bean注入Chinese Bean中,还需要使用lookup方法注入来管理Pen Bean与Chinese Bean之间的依赖关系。其大致需要两步:
- 将调用者Bean的实现类定义为抽象类,并定义一个抽象方法来获取被依赖的Bean;(经测试,具体类也能成功)
- 在<bean../>元素中添加<lookup-method../>子元素,让Spring为调用者Bean的实现类实现指定的抽象方法。
3.1 实现被依赖Bean
被依赖的Bean为多例模式:
package com.wj.chapter5.life.lookup; public class Pencil implements Pen { @Override public String signName(String name) { return "我的名字是" + name; } }
3.2 实现主调Bean
主调Bean(Chinese Bean)为单例模式,其依赖于多例Bean(Pen):
package com.wj.chapter5.life.lookup; /** * Chinese为单例模式,其依赖的Pen为多例 */ public abstract class Chinese implements Person { private String name; private Pen pen; public void setName(String name) { this.name = name; } // 定义抽象方法,该方法用于获取被依赖Bean public abstract Pen getPen(); @Override public void signName() { pen = getPen(); System.out.println("签名的笔型号:" + pen); System.out.println("我是中国人," + pen.signName(name)); } }
3.3 XML配置文件
<lookup-method../>元素需要指定两个属性:
- name:指定需要让Spring实现的方法
- bean:指定Spring实现该方法的返回值
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"> <bean id="chinese" class="com.wj.chapter5.life.lookup.Chinese"> <property name="name" value="熊燕子"></property> <!-- Spring只要检测到lookup-method元素,Spring会自动为该元素的name属性所指定的方法提供实现体。--> <lookup-method name="getPen" bean="pencil"/> </bean> <!-- 指定Pencil Bean的作用域为prototype,希望程序每次使用该Bean时用到的总是不同的实例 --> <bean id="pencil" class="com.wj.chapter5.life.lookup.Pencil" scope="prototype"></bean> </beans>
3.4 测试代码
package com.wj.chapter5.life.lookup; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringTest { // 1.指明xml配置文件位置,便于Spring读取,从而知道Bean的相关信息 private static final String PATH_XML = "com/wj/chapter5/life/lookup/applicationContext-lookup.xml"; @SuppressWarnings("resource") public static void main(String[] args) { // 2.以类加载路径下的xml文件作为配置文件,创建Spring容器 ApplicationContext ctx = new ClassPathXmlApplicationContext(PATH_XML); // 3.两次获取单例Person对象 Person p1 = ctx.getBean("chinese" , Person.class); Person p2 = ctx.getBean("chinese" , Person.class); // 4. 首先验证两次获取的单例Person是否是同一个对象 System.out.println("两次获取的单例Person是否是同一对象:" + (p1 == p2)); // 5. 验证依赖的多例Pencil对象是否确实是多例的 p1.signName(); p2.signName(); } }
测试结果如下:
可见,lookup方法注入可以正确实现singleton Bean依赖prototype Bean。
3.5 补充说明
前面实现Person接口时,将Chinese定义为抽象类,并在里面定义抽象方法getPen()用于获取多例Pen。但这与我们习惯不符:Chinese Bean是业务上需要使用的,并不需要定为abstract抽象类,我们在开发中也确实没明确拿到抽象类Chinese的实现类(实际上Spring给我们返回的Bean就是Chinese的实现,只不过对我们透明)。
经过测试,可以将Chinese定义为具体类,getPen()定义为空实现即可。Spring会自动帮我们实现getPen()方法的逻辑:
package com.wj.chapter5.life.lookup; /** * Chinese为单例模式,其依赖的Pen为多例 * 此处将Chinese定义为具体类,getPen为空实现 */ public class Chinese2 implements Person { private String name; private Pen pen; public void setName(String name) { this.name = name; } // 该方法用于获取被依赖Bean,此处未空实现 public Pen getPen() { return null; } @Override public void signName() { pen = getPen(); System.out.println("签名的笔型号:" + pen); System.out.println("我是中国人," + pen.signName(name)); } }
测试结果与之前一样。
代码地址链接:http://pan.baidu.com/s/1dFJ5UQt 密码:dnjf
相关推荐
《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练使用...
《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练使用...
- Bean的生命周期管理,作用域(singleton、prototype)。 - Spring MVC工作流程,HandlerMapping和HandlerAdapter。 - AOP的实现:动态代理(JDK、CGLIB)和AspectJ。 - Spring Boot的自动配置原理,Spring ...
在Spring框架中,ThreadLocal的应用非常广泛,尤其是在请求作用域的Bean管理、事务管理、任务调度和AOP等方面。例如,在Spring的DAO模板类中,尽管底层的数据连接或会话资源是非线程安全的,但是通过使用ThreadLocal...
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
内容概要:本文详细探讨了大语言模型(LLMs)在教育应用中遇到的知识冲突问题,包括概念定义、事实陈述和逻辑推理层面的认知不一致性。文章分析了知识冲突的技术成因,如训练数据噪声、参数化知识表示的局限、推理机制的缺陷、模型架构的不足及外部知识的偏差,并探讨了这些因素对教育应用的深远影响。文中提出了多维度的解决路径,如通过数据增强优化知识表示、利用提示强化上下文连贯、开发量规完善模型评估等。此外,文章从社会文化的宏观视角剖析了知识冲突的外部驱动因素,探讨如何在多元异质、动态演进的社会建构语境中构建开放进取、兼容融通的智能教育应用体系。 适合人群:从事教育技术研究的学者、教育工作者、人工智能研究人员和技术开发者。 使用场景及目标:①帮助教育工作者理解大语言模型在教育应用中的局限性;②为技术人员提供优化大语言模型教育应用的具体策略;③促进教育人工智能技术的可靠性、适应性和普及性提升。 其他说明:文章强调了知识冲突的有效化解不仅能够提升大语言模型在教育场景中的应用价值,还将为人工智能在更广泛领域的可持续发展奠定坚实基础。
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
数据结构day1-思维导图顺序表
STM32超声波红外避障小车项目通过STM32微控制器实现自动避障功能。硬件部分主要包括STM32开发板、超声波传感器、红外传感器、直流电机、电池模块和电机驱动模块。超声波传感器用于测量前方障碍物的距离,红外传感器帮助小车检测地面线路或障碍物。电机驱动模块通过STM32控制直流电机的转动,从而实现小车的前进、后退和转向。 在软件方面,STM32通过编写简单的避障算法,实时读取传感器数据,并根据环境信息控制小车的运动。当超声波传感器检测到障碍物时,系统会触发后退或转向操作,避免碰撞。
哈尔滨工业大学DeepSeek公开课-从图灵测试到DeepSeek.pdf
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
app开发
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
Screenshot_2025-03-31-19-36-01-657_com.UCMobile.jpg
半导体过程控制篇 集成电路的可靠性仿真_03_31_153111.docx
社交应用_鸿蒙OS_API12_高仿微信APP_开发示例_1742847098.zip
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
app开发