专项攻克-SpringBoot启动后 Bean的实例数量问题

文章目录

SpringBoot Bean 实例数量面试题

核心答案

默认情况下:单例,整个Spring容器中这个Bean只有1个实例,但不是所有Bean都只有一个实例,由Scope作用域决定。

默认scope:@Scope("singleton") 单例。

5种Scope作用域

作用域 实例数量 说明
singleton(默认) 整个容器仅1个实例 Spring容器启动初始化(或懒加载),全局复用,绝大多数业务Bean
prototype 每次获取都新建一个对象 每次getBean()、@Autowired注入都创建新实例
request 每个HTTP请求1个实例 Web环境,一次请求一个bean
session 每个用户会话1个实例 Web环境,一个session一个bean
application Servlet上下文1个实例 整个web应用共享1个,和singleton类似

注意:request / session / application 只在web(SpringMVC)环境生效。

注解写法

复制代码
// 多例,每次拿都新建对象
@Scope("prototype")
@Component
public class DemoService {
}

⚠️高频坑点(面试必问)

坑1:单例Bean里面注入prototype多例Bean,不会产生新对象

复制代码
@Component // singleton单例
public class AService {
    @Autowired
    private BService bService; // BService上加了@Scope("prototype")
}

现象:AService是单例,容器创建AService的时候,只注入一次BService ,之后一直复用同一个BService,并不会每次调用都新建B。

原因:依赖注入只发生在A初始化那一次。

解决方案3种:

  1. 注入 ObjectProvider<BService>,每次getObject()获取新实例

    @Autowired
    private ObjectProvider bServiceProvider;

    // 使用的时候
    BService b = bServiceProvider.getObject();

  2. 注入ApplicationContext,手动getBean("bService")

  3. 使用代理模式 @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)

坑2:单例Bean不要有成员变量(非线程安全)

singleton多线程共用同一个对象,如果Bean里面有成员变量存业务数据,并发会出现数据错乱!

✅正确:成员变量只用无状态对象(mapper、dao、配置);业务变量放方法局部变量。


面试问答

Q:Spring中Bean默认是单例,是单例模式的饿汉式还是懒汉式?

答:

  • 默认饿汉式:容器启动时就创建singleton bean;

  • 如果加 @Lazy 懒加载,变成懒汉式,第一次使用的时候才创建实例。

    @Component
    @Lazy // 容器启动不创建,第一次获取才创建
    public class DemoService{}

Q:@Controller、@Service、@Repository、@Component 是什么scope?

全部默认 singleton 单例。

Q:prototype的Bean什么时候销毁?

singleton:容器关闭的时候Spring帮调用销毁方法;

prototype:Spring容器不管理销毁!容器不会帮你执行destroy回调,需要自己手动销毁。

Q:SpringBoot web项目中Controller是单例吗?会不会线程安全问题?

Controller默认singleton。

只要不要定义成员变量存请求数据就线程安全;请求参数全部放在方法参数,局部变量,多线程互不干扰。


三句背诵版(面试口述)

  1. Spring Bean默认scope是singleton,整个IOC容器只有一个实例;可以通过@Scope改成prototype多例,每次获取新建对象。
  2. 单例Bean注入多例Bean会出现"多例失效",因为依赖注入只发生一次,可以用ObjectProvider解决。
  3. singleton Bean要保证无状态,不能用成员变量存业务数据,避免并发线程安全问题;prototype BeanSpring不负责销毁。
相关推荐
独隅4 分钟前
Claude 高效使用指南深度评测
java·开发语言·claude·claude code
ByteCoder.12 分钟前
班前十分钟的清单,按体检引导单来写
java·服务器·前端·助播虾
海的透彻14 分钟前
如何让docker容器启动时用自定义的用户
java·docker·dubbo
疯狂学习GIS18 分钟前
将谷歌地球引擎账号升级为Contributor与Partner层级的方法
java·数据库·人工智能
GG.WinGel30 分钟前
质数数目(蓝桥杯练习题)
java·数据结构·算法·青少年编程·蓝桥杯
泡泡糖的中文规格书35 分钟前
HDLbits 2.2 学习笔记 · 多路复用器
java·开发语言
John_Hui37 分钟前
第 3 篇:配置 JDK 17 环境
java·开发语言·ubuntu
秋天的怀念_David42 分钟前
算法一千零一夜 · 第十七夜 长街点灯
java·程序人生·算法
不吃鱼的羊1 小时前
如何应对恐惧
java
不吃鱼的羊1 小时前
如何建立高自尊
java·服务器·前端