文章目录
- [SpringBoot Bean 实例数量面试题](#SpringBoot Bean 实例数量面试题)
-
- 核心答案
- 5种Scope作用域
- ⚠️高频坑点(面试必问)
- 面试问答
-
- Q:Spring中Bean默认是单例,是单例模式的饿汉式还是懒汉式?
- [Q:@Controller、@Service、@Repository、@Component 是什么scope?](#Q:@Controller、@Service、@Repository、@Component 是什么scope?)
- Q:prototype的Bean什么时候销毁?
- [Q:SpringBoot web项目中Controller是单例吗?会不会线程安全问题?](#Q:SpringBoot web项目中Controller是单例吗?会不会线程安全问题?)
- 三句背诵版(面试口述)
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种:
-
注入
ObjectProvider<BService>,每次getObject()获取新实例@Autowired
private ObjectProviderbServiceProvider; // 使用的时候
BService b = bServiceProvider.getObject(); -
注入ApplicationContext,手动
getBean("bService") -
使用代理模式
@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。
只要不要定义成员变量存请求数据就线程安全;请求参数全部放在方法参数,局部变量,多线程互不干扰。
三句背诵版(面试口述)
- Spring Bean默认scope是singleton,整个IOC容器只有一个实例;可以通过@Scope改成prototype多例,每次获取新建对象。
- 单例Bean注入多例Bean会出现"多例失效",因为依赖注入只发生一次,可以用ObjectProvider解决。
- singleton Bean要保证无状态,不能用成员变量存业务数据,避免并发线程安全问题;prototype BeanSpring不负责销毁。