专项攻克-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不负责销毁。
相关推荐
JimmtButler1 小时前
功能明明正常,架构为什么还是会腐化?<第一章>
后端·架构
用户077911816611 小时前
记一次 yfinance 源码调试:SOCKS5 代理下 Chart API 正常,历史数据却一直超时
后端
步行cgn1 小时前
PageHelper 的用法
java·后端
foggyprojects1 小时前
业务系统有表格,BI 有看板,AI 问数还需要做什么?
后端
生锈的键盘1 小时前
深入理解 Socket 与 epoll:从内核数据结构到用户态回调的全链路解析
后端
Sam_Deep_Thinking1 小时前
从REST到gRPC,一个API选型的思考框架
java·后端·程序员
无毁的湖光-Al2 小时前
解Bug之路-with AI-应用被限流?
java·linux
程序员贺加贝2 小时前
别把 ThreadLocal 写进 Serializer:一次 SaaS 多租户 Jackson 上下文污染排查
java·spring boot
程序员爱钓鱼2 小时前
Rust const泛型详解:让常量也成为泛型参数
后端·面试·rust