Spring Bean的Scope作用域详解
Spring Bean的Scope作用域
Spring框架中的Bean Scope(作用域)用于控制Bean的生命周期和可见性。
Spring提供了多种作用域,每种作用域决定了Bean在应用中的创建和管理方式。
以下是Spring中最常用的作用域及其特点:
Scope作用域类型
1. Singleton(单例)
- 默认作用域: 如果没有显式指定作用域,默认就是Singleton。
- 生命周期: 在整个应用中,只有一个实例。这个实例在Spring容器启动时创建,并且在整个应用运行期间一直存在。
- 适用场景: 适用于无状态的Bean,如服务层和DAO层的Bean。
@Component @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) public class MySingletonComponent { // ... }
2. Prototype(原型)
- 生命周期: 每次请求都会创建一个新的实例。Spring容器在创建原型Bean后,就不再管理其生命周期。
- 适用场景: 适用于有状态的Bean,如需要每个请求都独立处理的Bean。
@Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class MyPrototypeComponent { // ... }
在Spring框架中,使用@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
修饰的@Component
表示该组件是一个原型(Prototype)作用域的bean。
这意味着每次通过Spring容器请求这个bean时,都会创建一个新的实例。
与单例(Singleton)作用域的bean不同,原型作用域的bean不会被缓存,每次请求都会返回一个新的实例。
生命周期
每次请求都创建新实例:
- 每次调用
context.getBean(MyPrototypeComponent.class)
时,都会创建一个新的MyPrototypeComponent
实例。 - 这意味着每个请求之间是隔离的,每个实例都有独立的状态。
生命周期管理:
- 原型作用域的bean的生命周期由创建它的客户端代码负责管理。Spring容器只负责初始化和装配bean,一旦bean被创建并返回给客户端代码,容器就不再管理其生命周期。
- 容器不会调用销毁方法(如
@PreDestroy
注解的方法)来清理资源,因为容器不知道何时应该销毁这些bean,这也反向说明了原型Bean被Spring创建后就不在管理其生命周期了。
在Spring框架中,当一个Bean的作用域被设置为SCOPE_PROTOTYPE
时,这个Bean在容器启动时不会被自动实例化。相反,每次通过Spring容器请求这个Bean时,才会创建一个新的实例。
关键总结
Singleton作用域:
- 默认作用域。
- 在容器启动时被实例化一次。
- 整个应用生命周期内只存在一个实例。
Prototype作用域:
- 每次请求时都会创建一个新的实例(也是每次请时才会创建,一个被定义为该作用域的类如果没有在任何地方使用它,那么你可以认为它和一个普通的Java类没有区别)。
- 请求的方式包括注入该Bean到其他Bean里,每注入一个地方都是一个独立的Bean。或者使用
context.getBean
方式获取Bean的时候。 - 容器启动时不会自动实例化。
- 容器在创建Bean后不再管理其生命周期。
- 特别适合那种需要注入Spring中其他类的Java类,但是这个类又是在某些场景需要的时候才需要实例化的场景,例如实现 Runnable 接口的线程任务类。
示例:
@Data @Accessors(chain = true) @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class Task implements Runnable { private TaskInfo taskInfo; // 注入对象 @Autowired private TaskService taskService; @Override public void run() { taskService.process(taskInfo); } }
// 调用示例代码 ApplicationContext context = xxx; ExecutorService executor = xxx; TaskInfo taskInfo = xxx; // 这里每次getBean获取的Task对象都是一个新的实例 Task task = context.getBean(Task.class).setTaskInfo(taskInfo); executor.execute(task);
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
apollo更改配置刷新@ConfigurationProperties配置类
这篇文章主要为大家介绍了apollo更改配置刷新@ConfigurationProperties配置类示例解析,apollo更改配置刷新@ConfigurationProperties配置类2023-04-04java线程Thread.sleep()对比对象的wait示例解析
这篇文章主要为大家介绍了java线程Thread.sleep()对比对象的wait示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-09-09SpringBoot配置Spring Security的实现示例
本文主要介绍了SpringBoot配置Spring Security的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2024-10-10解决springSecurity 使用默认登陆界面登录后无法跳转问题
这篇文章主要介绍了解决springSecurity 使用默认登陆界面登录后无法跳转问题,项目环境springboot下使用springSecurity 版本2.7.8,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧2023-12-12Java 8中Stream API的这些奇技淫巧!你Get了吗?
这篇文章主要介绍了Java 8中Stream API的这些奇技淫巧!你Get了吗?文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2019-08-08
最新评论