侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

Spring Bean的作用域有哪些?请说明它们的区别及适用场景

2025-12-5 / 0 评论 / 5 阅读

题目

Spring Bean的作用域有哪些?请说明它们的区别及适用场景

信息

  • 类型:问答
  • 难度:⭐⭐

考点

Bean作用域, 线程安全, 生命周期管理, 配置方式

快速回答

Spring Bean 支持五种核心作用域:

  • singleton(默认):每个容器中只有一个实例
  • prototype:每次请求都创建新实例
  • request:每个HTTP请求创建一个实例
  • session:每个HTTP会话创建一个实例
  • application:每个ServletContext生命周期一个实例

关键区别:
1. singleton 全局共享需注意线程安全
2. prototype 适用于有状态的场景
3. Web相关作用域需在Web环境中使用

解析

1. 作用域详解及配置方式

配置示例(注解方式):

// XML配置
<bean id="service" class="com.example.Service" scope="prototype"/>

// 注解配置
@Bean
@Scope("prototype")
public Service service() {
    return new Service();
}

// 或使用常量
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)

2. 核心作用域对比

作用域生命周期线程安全适用场景
singleton容器初始化时创建(懒加载除外),容器销毁时销毁需自行保证无状态服务、工具类、数据库连接池
prototype每次getBean()时创建,容器不管理销毁天然隔离有状态对象(如购物车)、需要隔离的组件
requestHTTP请求开始时创建,请求结束时销毁天然隔离存储请求相关数据(如用户表单)
session会话创建时创建,会话超时/结束时销毁天然隔离用户会话数据(如登录信息)
applicationServletContext生命周期需自行保证全局缓存、共享资源

3. 最佳实践与常见错误

最佳实践:

  • 优先使用singleton:减少对象创建开销,但需确保无状态
  • prototype作用域中避免持有长期资源:需手动释放资源(如文件句柄)
  • Web作用域代理模式:解决注入问题
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)

常见错误:

  • 错误1:在singleton中注入prototype Bean(需用方法注入解决)
  • 错误2:在非Web环境使用request/session作用域
  • 错误3:prototype Bean中忘记释放资源导致内存泄漏

4. 原理说明

Spring通过BeanDefinition存储作用域配置,由Scope接口实现具体行为:

public interface Scope {
    Object get(String name, ObjectFactory<?> objectFactory);
    Object remove(String name);
    // ...
}

容器在创建Bean时:
1. 检查作用域类型
2. 调用对应的Scope实现(如SingletonScope/PrototypeScope
3. 对于Web作用域,通过RequestContextListenerRequestContextFilter绑定生命周期

5. 扩展知识

  • 自定义作用域:实现Scope接口并注册
    // 注册自定义作用域
    context.getBeanFactory().registerScope("thread", new SimpleThreadScope());
  • 作用域代理:解决作用域依赖问题(CGLIB/JDK动态代理)
  • Jakarta EE 的@SessionScoped:需实现Serializable接口