专项攻克-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不负责销毁。
相关推荐
乌暮9 小时前
Spring AOP 与 Spring 事务:用大白话彻底理解原理与实践
java·数据库·spring boot·后端·sql·学习·spring
YDS8299 小时前
Small Spring IOC篇:容器事件及其监听器
java·spring
金銀銅鐵9 小时前
带您看懂字节码指令(三):一行加法里有什么
java·jvm
文丑颜不良啊9 小时前
LeetCode2921~2940题目解析
java·leetcode
我不会起名字3229 小时前
未接入最终读上限的参数:`websocketMaxMsgLen` 与 12.5 倍差距
后端·websocket·go·即时通讯·im·故障排查
一条Go10 小时前
接收方合并去重:同一个人为什么只该收到一次通知
后端·架构·github
北漂人Java10 小时前
基于 Spring AI Alibaba WorkFlow 构建 Java 生产级 AI Agent
java·人工智能·spring
张一凡9310 小时前
给 Coding Agent 加一道"架构闸门":Jin 是如何做到"先审架构、再写代码、不漂移"的
前端·后端·agent
Jvav练习生11 小时前
AI Agent 总在关键时刻“失忆”翻车?一文讲透上下文工程(附可运行 Python 代码)
后端
用户1129361121911 小时前
编译全绿,上线就崩:MyBatis 五层方法名大小写埋下的坑
java