prototype 注入到 singleton 里,prototype是否还是线程安全的

作者:swordbob日期:2026/6/12

"如果 prototype Bean 内部没有共享状态,自身是线程安全的。但 Spring 容器对 prototype 的多例行为有'陷阱',可能导致实际使用中不安全。"

展开讲:

prototype 注入到 singleton 里的线程安全分析

一、prototype Bean 自身的线程安全性

1.1 prototype 本身是"独立实例"(这个是安全的

@Service@Scope("prototype")public class ShoppingCart { private List<Item> items = new ArrayList<>(); public void addItem(Item item) { items.add(item); // 操作的是自己的成员变量 }}

为什么自身是线程安全的?

特性解释
每个 prototype 实例独立1000 个调用 → 1000 个 ShoppingCart 实例,互相不共享
每个实例的成员变量独立线程 A 操作 cart1.items,线程 B 操作 cart2.items,互不干扰
GC 独立一个实例的 GC 不影响其他实例

**所以 prototype Bean 本身是线程安全的,前提是你每次都拿到了不同的实例

1.2 但这里有"陷阱"——老哥 7+ 年必须知道

如果不加 proxyMode,singleton 里的 prototype 不是"真多例"

@Service // singletonpublic class OrderService { @Autowired private ShoppingCart cart; // ⚠️ 看着像 prototype}

实际行为:

  • OrderService 是单例,整个应用只有 1 个
  • cartOrderService 创建时注入一次
  • cart 永远是同一个 ShoppingCart 实例!
  • 1000 个请求都共享同一个 cart → 多线程同时改 cart.items → 线程不安全!

二、3 种场景的线程安全分析

场景 1:纯 prototype(不注入到 singleton,直接 getBean

ApplicationContext ctx = ...;ShoppingCart cart1 = ctx.getBean(ShoppingCart.class); // 实例 1ShoppingCart cart2 = ctx.getBean(ShoppingCart.class); // 实例 2(不同对象)

线程安全:✅ 是

  • 每次 getBean 都返回新实例
  • 多个线程拿到不同实例
  • 互不干扰
场景 2:prototype 注入到 singleton(不加 proxyMode

@Service // singletonpublic class OrderService { @Autowired private ShoppingCart cart; // 注入时拿到一次}

线程安全:❌ 否

  • 整个应用 1 个 OrderService
  • 整个应用 1 个 cart(注入时定下来)
  • 多线程共享同一 cart → 不安全
场景 3:prototype + proxyMode / @Lazy(真正多例

@Service@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)public class ShoppingCart { ... }@Servicepublic class OrderService { @Autowired private ShoppingCart cart; // 代理对象}

线程安全:✅ 是

  • 注入的是代理对象
  • 每次调用 cart 方法时,代理内部创建一个新的 ShoppingCart
  • 1000 个请求 → 1000 个不同 ShoppingCart → 互不干扰

三、Spring 多例的 4 个"坑"(老哥面试加分

坑 1:注入时拿到一次(最常踩

@Servicepublic class A { @Autowired private PrototypeBean b; // ⚠️ 整个 A 共享同一个 b}

解决: proxyMode = TARGET_CLASS@Lazy

坑 2:@Async 注解的方法内 prototype 失效

@Service@Scope("prototype")public class TaskRunner { ... }@Servicepublic class TaskService { @Autowired private TaskRunner runner; @Async // 异步调用 public void run() { // 这里 runner 是多少个?看注入方式 }}

坑:

  • 如果 @Autowired 直接注入,runner 永远同一个
  • 必须用 ObjectProvider<TaskRunner> 每次 .getObject() 才拿到新实例
坑 3:prototype 在 @Configuration 里 @Bean 不会自动多例

@Configurationpublic class AppConfig { @Bean @Scope("prototype") public ShoppingCart cart() { return new ShoppingCart(); }}

坑:

  • 这种写法是真的多例(每次 getBean 都新建)
  • 调用 cart() 方法本身只返回同一个对象(因为 Spring 拦截了 @Bean 方法)
  • 实际多例要靠其他 Bean 注入或 getBean 触发
坑 4:prototype Bean 的销毁不归 Spring 管

@PreDestroy // ⚠️ prototype Bean 上加这个不会生效public void cleanup() { // 永远不会调用}

解决:

  • 实现 DisposableBean 接口
  • BeanPostProcessor 手动管理

四、面试官追问应对

追问:prototype 注入到 singleton 里,prototype 还线程安全吗?

"分情况看

如果用 proxyMode / @Lazy 真正多例:✅ 线程安全(每个线程拿到不同实例)。

如果直接 @Autowired 不加处理:❌ 不安全(整个应用共享同一个 prototype 实例)。

核心坑:singleton Bean 创建时 prototype 注入一次,多线程共享。

追问 2:怎么判断当前 Bean 是不是 prototype?

// 运行时判断if (ctx.containsBean("xxx") && ctx.isPrototype("xxx")) { // 是 prototype}

追问 3:怎么让 singleton 注入 prototype 真的多例?

"3 种方法

1.@Scope + proxyMode = TARGET_CLASS(最推荐)

2.@Lazy(延迟加载,代理对象)

3.ObjectProvider<PrototypeBean> + .getObject()最灵活)"

追问 4:ObjectProvider 怎么用?

@Servicepublic class OrderService { @Autowired private ObjectProvider<ShoppingCart> cartProvider; // 不直接注入 public void checkout() { ShoppingCart cart = cartProvider.getObject(); // 每次调用拿到新实例 cart.addItem(...); }}

ObjectProvider 优点:

  • 显式控制获取时机
  • 不用加 @Scope / @Lazy / proxyMode
  • 项目里推荐用这个(最清晰)

六、面试答法模板

"3 句话讲清楚 prototype 线程安全

1.prototype 本身是独立的(每个实例不共享成员变量),所以自身线程安全

2.但注入到 singleton Bean 里时,不加 proxyMode / @Lazy 会变成'假多例'(整个应用共享同一实例),多线程并发改这个共享实例就线程不安全

3.**正确做法:proxyMode = TARGET_CLASS / @Lazy / ObjectProvider,**保证每次调用拿到新实例。

我做的 MOVA 报表生成器就是这个套路,proxyMode 让 100 个并发任务互不干扰。"

七、一句话总结

"prototype 自身线程安全,但注入到 singleton 不加 proxyMode 会变成'假多例',整个应用共享一个 prototype 实例,反而不安全。"


prototype 注入到 singleton 里,prototype是否还是线程安全的》 是转载文章,点击查看原文


相关推荐


局部两极分析破解数学建模难题
luj_17682026/6/5

当前博文未提及该问题,以下是基于C知道的知识内容为您回答 在数学建模中,通过“局部两极分析”实现问题求解的突破,其核心思想是:在复杂系统的局部或特定维度上,分别考察其极大化与极小化两种极端状态或趋势,通过分析这两种对立极值的行为、约束与相互作用,来洞察系统的本质结构、关键矛盾与优化路径,从而为全局问题的求解找到突破口。 这种方法融合了优化理论、博弈论和系统分析的思想。 一、 “局部两极分析”的核心逻辑与步骤 “局部两极分析”并非一个固定的算法,而是一种建模策略与思维框架。其通用实施流程可概


ASP.NET Core Razor 语法简述
叫我少年2026/5/30

如果写过 HTML 里嵌 <?php ?>​ 的页面吧?Razor 干的事差不多,只不过嵌入式用的是 C#。Razor 标记可以塞进 .cshtml​(MVC 视图/Razor Pages)或者 .razor​(Blazor 组件),写法跟 Vue 的模板语法有几分神似。下面从最基础的开始,一路讲到那些容易被忽视的坑。 1. 怎么输出 HTML Razor 的默认语言就是 HTML,你写 <p>Hello</p>​,它就乖乖输出 <p>Hello</p>​。但是想混入 C# 逻辑的时候,就得靠


Layui结合springboot读取返回值,前端展示简单示例
一个心烑2026/5/7

一、SpringBoot 后端接口 + Layui 前端页面实现 1 后端返回 JSON 数据 2 前端 Layui 表格展示数据 3 前端表单提交保存到后端 4 完整的异步请求(Ajax)处理 项目结构(标准 SpringBoot): springboot-layui-demo/ ├── src/main/java/com/demo/ │ ├── controller/ │ │ └── UserController.java # 接口控制器 │ ├── entity/ │


算个账也要开顶配 AI?我让 AI 自己劝我换了个小的
小墨同学boy2026/4/28

其实我自己每个月在 AI 上花的钱不少,Claude、GPT、GLM 都有订阅。但其实有很大一部分预算其实是花在处理生活琐事上的——记账、外卖归类、做一个消费数据分析。这种活差不多每天都得跑一遍,所以token 烧得也不少,尤其是有时候开了深度思考的模型反而更容易给错数据。 后来我才反应过来,手里订阅一个不少,结果我一直在拿 Opus 的钱让它当我的计算器。有点奢侈了,所以我准备切换思路看看有没有节省token的办法。 一、我发现一个反直觉的事 在日常生活当中,我的直觉一直是有钱就上好的贵的效果


2026 年前端工程师面试:一份来自面试官视角的真实复盘
怕浪猫2026/4/19

前言:为什么我要写这篇文章 前两天和一个在高校和企业都面试过不少候选人的"面试官老炮"聊天,他听过太多候选人抱怨面试内容脱离实际、工作用不到。也听过面试官抱怨候选人只会背题、动手能力差。有意思的是,这两拨人的抱怨,往往都对。 今天我想换个视角——不站在候选人角度刷题,也不站在理论派角度讲八股文,而是站在有实际招聘需求、真正要带团队干活的面试官视角,聊聊 2026 年的前端工程师面试,到底在考什么、为什么这么考。 核心结论先行 2026 年的前端面试,考察维度已经发生了结构性变化:


【折腾】windows下小狼毫输入法更新字库
stereohomology2026/4/11

我问DeepSeek如何更新,而不是自己从文档里面找,结果效率很高、回答很全面,直接给出步骤和命令。 作为菜鸟,我用第一种方法: 这个错误提示很明确:你当前所在的目录(即小狼毫的用户文件夹)不是空的,而 git clone 要求目标目录必须是空目录才能执行。 小狼毫默认安装后,用户文件夹里会自带一些基础配置文件(比如 default.custom.yaml、weasel.custom.yaml、luna_pinyin.schema.yaml 等)。直接 git clone 到非空目录就会报这个


吴恩达《LangChain LLM 应用开发精读笔记》8-Document Loading 文档加载
勇气要爆发2026/4/3

大家好,我是飞哥!👋 欢迎来到吴恩达《LangChain:Chat with Your Data》系列课程的第二讲。上一讲我们了解了 RAG 的全流程,今天我们正式开工,攻克第一关:Document Loading (文档加载)。 1. 为什么:Garbage In, Garbage Out 🗑️ 💡 场景锚定 做饭要先买菜洗菜,训练 AI 也是一样。如果你喂给 AI 的数据格式乱七八糟、乱码满天飞,那么 AI 输出的答案肯定也是一塌糊涂。 PDF 里有复杂的表格和页眉页脚。网页里有一堆


CSS 全栈指南:从基础到 2025 新特性
橘子编程2026/3/25

CSS 知识详解 从层叠规则到现代布局,从自定义属性到容器查询,系统梳理 CSS 全栈知识,涵盖 W3C 2025 最新特性,助你写出优雅、高性能的样式代码。 目录 什么是 CSS语法与引入方式层叠与继承选择器优先级CSS 选择器大全伪类与伪元素CSS 盒模型Display 与定位Flexbox 弹性布局Grid 网格布局字体与文本颜色与背景变换与过渡CSS 动画自定义属性(变量)响应式设计现代 CSS 特性最佳实践 一、什么是 CSS CSS(Cascading S


【宇树机器人强化学习】(二):ActorCritic网络和ActorCriticRecurrent网络的python实现与解析
zh路西法2026/3/17

前言 Unitree RL GYM 是一个开源的 基于 Unitree 机器人强化学习(Reinforcement Learning, RL)控制示例项目,用于训练、测试和部署四足机器人控制策略。该仓库支持多种 Unitree 机器人型号,包括 Go2、H1、H1_2 和 G1。仓库地址 本系列将着手解析整个仓库的核心代码与算法实现和训练教程。此系列默认读者拥有一定的强化学习基础和代码基础,故在部分原理和基础代码逻辑不做解释,对强化学习基础感兴趣的读者可以阅读我的入门系列: 第一期


Git Worktree / Worktrunk:并行 AI 开发工作流实战
RickeyBoy2026/3/9

最近在日常开发中尝试了用 Git Worktree (Worktrunk) 配合 Claude Code 进行并行开发,体验下来效果非常好。这篇文章就来分享一下这套工作流的搭建和使用经验,希望能对大家有点帮助~ 欢迎大家点个 star:Github 以及下载我的独立 app: iColors 一、为什么需要 Git Worktree 先说一个日常开发中很常见的场景:你正在开发一个新功能,突然来了一个紧急 bug 需要修复。通常你要么 git stash,要么 git commit 一个半成品

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读