Spring bean的作用域有哪些?

spring 的 controller 是单例还是多例,怎么保证并发的安全。

spring bean 作用域有五种:

  • singleton:单例模式,当 spring 创建 applicationContext 容器的时候, spring 会欲初始化所有的该作用域实例,加上 lazy-init 就可以避免预处 理;

  • prototype:原型模式,每次通过 getBean 获取该 bean 就会新产生一个 实例,创建后 spring 将不再对其管理;


下面是在 web 项目下才用到的

  • request:搞 web 的大家都应该明白 request 的域了吧,就是每次请求都 新产生一个实例,和 prototype 不同就是创建后,接下来的管理, spring 依然在监听。
  • session:每次会话,同上。
  • global session:全局的 web 域,类似于 servlet 中的 application。 spring 中的 controller 默认是单例,也就是 singleton 模式了。
    所以如果 controller 中有一个私有变量 a,所有请求到同一个 controller 时,使 用的 a 变量都是共用的,即若是某个请求修改了这个变量 a,则,在别的请求 中能够读到这个修改的内容。 为了保证并发的安全,常见有两种解决方法。
  • 在 controller 中使用 ThreadLocal 变量。
  • 在 spring 配置文件 Controller 中声明为 scope=“prototype”,每次都创 建新的 controller,不再使用单例模式。 另外,Servlet 也不是线程安全的,Servlet 是单实例多线程的,当多个线程同时 访问同一个方法,是不能保证共享变量的线程安全性的。
<think>嗯,用户之前已经问过关于Bean的基本概念,现在接着问Spring Bean作用域。我需要先回顾一下之前的问题,确保回答连贯。用户可能正在学习Spring框架,需要了解Bean的不同作用域来更好地管理应用中的对象生命周期。 首先,我要列出Spring Bean的所有作用域,但得确认版本。Spring默认的作用域在文档里是五个还是六个?记得从Spring 3开始有request、session、application,还有websocket作用域,但可能用户用的是较新的版本,所以得检查最新的作用域是否有变化。 默认的作用域应该是单例(singleton)和原型(prototype),而web相关的如request、session、application和websocket。要确保不遗漏这些。然后,每个作用域需要简单解释,并给出使用场景的例子,这样用户更容易理解。 用户可能想知道如何配置这些作用域,所以需要提到注解方式,比如@Scope,或者XML配置。同时,需要指出常见的错误,比如在单例Bean中注入原型Bean可能导致的问题,以及如何解决,比如用provider或者方法注入。 另外,用户可能对作用域的实际应用场景不太清楚,所以举一些例子,比如用户登录信息用session作用域,HTTP请求相关的数据用request作用域,这样更具体。 还要注意提到自定义作用域的可能性,虽然高级,但用户可能有兴趣了解扩展性。不过这部分可以简要带过,避免信息过载。 最后,检查是否有遗漏的作用域,确认Spring的最新版本是否有新增或变化。比如,application作用域对应的是ServletContext,而globalSession在Portlet环境中使用,但现在Portlet可能不太常用,是否需要提到?可能需要说明它适用于Portlet应用,但多数情况下可能用不到,避免混淆用户。 总结一下,回答的结构应该是先总述作用域的作用,然后分点列出每个作用域,解释其含义和使用场景,最后给出配置方式和注意事项。确保语言简洁明了,符合用户的中文理解习惯。</think>Spring Bean作用域定义了Bean在容器中的生命周期和可见范围。以下是Spring支持的**6种核心作用域**及其适用场景: --- ### **1. 单例作用域(Singleton,默认)** - **定义**:整个容器中仅存在一个实例,所有请求共享同一个Bean。 - **适用场景**:无状态的工具类、配置类、服务类等。 - **配置方式**: ```java @Scope("singleton") @Bean public MyBean myBean() { ... } ``` --- ### **2. 原型作用域(Prototype)** - **定义**:每次请求都创建新实例。 - **适用场景**:需要维护独立状态的场景(如用户会话数据)。 - **注意事项**:需自行管理销毁逻辑(容器不负责原型Bean的销毁)。 ```java @Scope("prototype") ``` --- ### **3. 请求作用域(Request)** - **定义**:每个HTTP请求创建一个新实例,请求结束后销毁。 - **适用场景**:HTTP请求相关的数据(如表单提交参数)。 - **配置要求**:需在Web环境中使用(如Spring MVC)。 ```java @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) ``` --- ### **4. 会话作用域(Session)** - **定义**:每个用户会话(Session)创建一个实例,会话过期后销毁。 - **适用场景**:用户登录信息、购物车数据等。 ```java @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) ``` --- ### **5. 应用作用域(Application)** - **定义**:整个Web应用共享一个实例(类似单例,但绑定到ServletContext生命周期)。 - **适用场景**:全局缓存、共享资源。 ```java @Scope(value = WebApplicationContext.SCOPE_APPLICATION) ``` --- ### **6. WebSocket作用域(WebSocket)** - **定义**:每个WebSocket会话创建一个实例,会话关闭后销毁。 - **适用场景**:实时通信(如聊天室消息管理)。 ```java @Scope(scopeName = "websocket") ``` --- ### **扩展:自定义作用域** 通过实现`Scope`接口可定义自定义作用域(如线程作用域),需注册到容器: ```java ConfigurableBeanFactory.registerScope("customScope", new CustomScope()); ``` --- ### **作用域配置方式对比** | 方式 | 注解示例 | XML配置示例 | |--------|----------------------------------|-----------------------------------| | 单例 | `@Scope("singleton")` | `<bean scope="singleton"/>` | | 原型 | `@Scope("prototype")` | `<bean scope="prototype"/>` | | 请求 | `@RequestScope` | `<bean scope="request"/>` | | 会话 | `@SessionScope` | `<bean scope="session"/>` | --- ### **常见问题** 1. **单例Bean中注入原型Bean** - 问题:单例Bean依赖的原型Bean不会刷新。 - 解决:使用`Provider`或方法注入: ```java @Autowired private Provider<PrototypeBean> prototypeBeanProvider; ``` 2. **代理模式(ProxyMode)** 在Web作用域中需设置`proxyMode`以延迟初始化(如`TARGET_CLASS`表示使用CGLIB代理)。 --- **总结**:选择合适的作用域需结合具体业务场景,避免因作用域误用导致内存泄漏或状态混乱。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值