”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > Singleton 和原型 Spring Bean 范围:详细探索

Singleton 和原型 Spring Bean 范围:详细探索

发布于2024-11-06
浏览:151

Singleton and Prototype Spring Bean Scopes: A Detailed Exploration

当我第一次开始使用 Spring 时,最让我感兴趣的概念之一是 bean 范围的想法。 Spring 提供了各种 bean 作用域,用于确定在 Spring 容器内创建的 bean 的生命周期。最常用的两个范围是 Singleton 和 Prototype。了解这些范围对于设计高效且有效的 Spring 应用程序至关重要,所以让我带您了解我对它们的了解。

了解 Spring Bean 范围

在Spring中,bean是一个由Spring IoC(控制反转)容器实例化、组装和管理的对象。 Bean 作用域是指 bean 的生命周期 - 创建 bean 实例的方式和时间,以及它们的持续时间。

Spring 提供了几个 bean 作用域,但我将重点关注的两个是:

  • 单例作用域
  • 原型范围

每个范围都有其特定的用例,选择正确的范围可以显着影响应用程序的行为和性能。

单例范围

Singleton 作用域是 Spring 中的默认作用域,也是我最常使用的作用域。当使用 Singleton 范围定义一个 bean 时,这意味着 Spring 容器将仅创建该 bean 的一个实例,并且该单个实例将在整个应用程序上下文中共享。

它是如何运作的

当我将一个 bean 声明为 Singleton 时,Spring 在第一次请求时(在应用程序上下文启动期间或首次引用它时)创建该 bean 实例。之后,对该 bean 的每个后续请求都将返回相同的实例。

这是一个简单的例子:

@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyService();
    }
}

在此示例中,myService() 是一个 Singleton bean。每次我从 Spring 上下文请求 MyService bean 时,我都会得到相同的实例。

Singleton Bean 的用例

我发现 Singleton 作用域非常适合无状态 Bean——那些不保存任何客户端特定信息的 Bean。示例包括:

  • 服务类:通常,这些类包含可以在应用程序之间共享的业务逻辑,而不需要单独的实例。
  • DAO 类:由于它们通常与数据库交互并且不维护特定于客户端的状态,因此单个实​​例就足够了。

优点和注意事项

Singleton beans 的主要优点是内存效率。通过重用单个实例,应用程序消耗更少的内存,并且创建和销毁对象的开销最小化。然而,对维护状态的 Singleton beans 保持谨慎是很重要的。如果 Singleton bean 无意中保存了状态(例如实例变量),则该状态可以在多个客户端之间共享,从而导致潜在的数据不一致。

原型范围

与 Singleton 相比,Prototype 范围在每次从 Spring 容器请求 bean 时都会创建一个新的 bean 实例。当我了解到这一点时,很明显 Prototype beans 对于每次使用都需要一个新实例的场景非常有用。

它是如何运作的

当使用 Prototype 作用域定义 bean 时,每次请求该 bean 时 Spring 都会返回一个新实例。以下是我定义 Prototype bean 的方式:

@Configuration
public class AppConfig {
    @Bean
    @Scope("prototype")
    public MyService myService() {
        return new MyService();
    }
}

在此示例中,每次我从 Spring 上下文请求 MyService bean 时,Spring 都会创建 MyService 的一个新实例。

原型 Bean 的用例

原型 bean 在处理有状态 bean 时特别有用——那些维护某种特定于客户端的状态或每次使用都需要唯一配置的 bean。一些典型的用例包括:

  • 命令对象:如果我要实现像 Command 这样的模式,其中每个命令单独执行并维护自己的状态,那么 Prototype bean 是正确的选择。
  • 会话或请求范围 Beans:在 Web 应用程序中,特定于用户会话或请求的 Bean 可以定义为原型,以确保为每个用户或请求创建一个新实例。

优点和注意事项

使用 Prototype beans 的主要优点是它在创建新实例时提供的灵活性。这在处理有状态对象时特别有用。然而,在性能和资源使用方面需要权衡。由于每次都会创建一个新实例,因此可能会导致更高的内存消耗和更频繁的垃圾收集。此外,与 Singleton bean 不同,Spring 不管理 Prototype bean 除了创建之外的生命周期,因此我必须手动处理这些 bean 的销毁和清理。

单例与原型:选择正确的范围

设计 Spring 应用程序时我面临的关键决策之一是在 Singleton 和 Prototype 范围之间进行选择。以下是我考虑的因素的总结:

  • 有状态:如果bean是无状态的,Singleton通常是最好的选择。对于有状态bean,Prototype 更合适。
  • 资源管理:单例 bean 的内存效率更高,因为只维护一个实例。原型 Bean 在提供更大灵活性的同时,也消耗更多资源。
  • 生命周期管理:单例 bean 在其整个生命周期中由 Spring 容器进行管理。相反,我必须管理 Prototype beans 的整个生命周期。

实际例子

让我提供一个实际场景,可能有助于阐明何时使用每个范围。假设我正在构建一个在线购物应用程序。

  • 购物车服务:该服务通常是无状态的,并且是 Singleton bean 的良好候选者。无需每次都创建新实例,同一个服务可以处理多个请求。
  • 订单处理:另一方面,代表客户订单的 Order 对象是有状态的,包含特定于该订单的详细信息。因此,它应该是一个 Prototype bean,以便每个订单都由 Order 类的单独实例处理。

混合范围:注意事项

我从惨痛的教训中学到的一件事是,混合使用 Singleton 和 Prototype beans 可能会导致意想不到的问题。例如,将 Prototype 范围的 bean 注入到 Singleton bean 中可能会导致 Singleton bean 始终使用 Prototype bean 的同一实例。为了避免这种情况,我通常注入一个 Provider 或使用 @Lookup 注释来确保每次需要时都会创建 Prototype bean 的新实例。

@Service
public class SingletonService {

    @Autowired
    private Provider myPrototypeServiceProvider;

    public void usePrototypeService() {
        MyPrototypeService prototypeService = myPrototypeServiceProvider.get();
        prototypeService.execute();
    }
}

在此示例中,myPrototypeServiceProvider.get() 确保每次在 Singleton bean 中调用时都会创建 MyPrototypeService 的新实例。

再见 !

理解 Spring 中的 Singleton 和 Prototype bean 范围的细微差别对于我作为开发人员的旅程至关重要。根据用例,这两种示波器都具有明显的优势,选择正确的示波器可以显着影响应用程序的性能和设计。

根据我的经验,Singleton 由于其效率和简单性而成为大多数 bean 的首选范围,而 Prototype 则保留给那些每次都需要新实例的特殊情况。通过仔细考虑 bean 的有状态性以及它们在应用程序中的使用方式,我可以做出明智的决策,从而构建更好、更易于维护的 Spring 应用程序。

版本声明 本文转载于:https://dev.to/isaactony/singleton-and-prototype-spring-bean-scopes-a-detailed-exploration-1gpl?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • PHP未来:适应与创新
    PHP未来:适应与创新
    PHP的未来将通过适应新技术趋势和引入创新特性来实现:1)适应云计算、容器化和微服务架构,支持Docker和Kubernetes;2)引入JIT编译器和枚举类型,提升性能和数据处理效率;3)持续优化性能和推广最佳实践。 引言在编程世界中,PHP一直是网页开发的中流砥柱。作为一个从1994年就开始发展...
    编程 发布于2025-05-16
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    编程 发布于2025-05-16
  • 在JavaScript中如何并发运行异步操作并正确处理错误?
    在JavaScript中如何并发运行异步操作并正确处理错误?
    同意操作execution 在执行asynchronous操作时,相关的代码段落会遇到一个问题,当执行asynchronous操作:此实现在启动下一个操作之前依次等待每个操作的完成。要启用并发执行,需要进行修改的方法。 第一个解决方案试图通过获得每个操作的承诺来解决此问题,然后单独等待它们: co...
    编程 发布于2025-05-16
  • 如何使用替换指令在GO MOD中解析模块路径差异?
    如何使用替换指令在GO MOD中解析模块路径差异?
    在使用GO MOD时,在GO MOD 中克服模块路径差异时,可能会遇到冲突,其中可能会遇到一个冲突,其中3派对软件包将另一个带有导入套件的path package the Imptioned package the Imptioned package the Imported tocted pac...
    编程 发布于2025-05-16
  • 如何限制动态大小的父元素中元素的滚动范围?
    如何限制动态大小的父元素中元素的滚动范围?
    在交互式接口中实现垂直滚动元素的CSS高度限制,控制元素的滚动行为对于确保用户体验和可访问性是必不可少的。一种这样的方案涉及限制动态大小的父元素中元素的滚动范围。问题:考虑一个布局,其中我们具有与用户垂直滚动一起移动的可滚动地图div,同时与固定的固定sidebar保持一致。但是,地图的滚动无限期...
    编程 发布于2025-05-16
  • 如何在无序集合中为元组实现通用哈希功能?
    如何在无序集合中为元组实现通用哈希功能?
    在未订购的集合中的元素要纠正此问题,一种方法是手动为特定元组类型定义哈希函数,例如: template template template 。 struct std :: hash { size_t operator()(std :: tuple const&tuple)const {...
    编程 发布于2025-05-16
  • Python元类工作原理及类创建与定制
    Python元类工作原理及类创建与定制
    python中的metaclasses是什么? Metaclasses负责在Python中创建类对象。就像类创建实例一样,元类也创建类。他们提供了对类创建过程的控制层,允许自定义类行为和属性。在Python中理解类作为对象的概念,类是描述用于创建新实例或对象的蓝图的对象。这意味着类本身是使用类关...
    编程 发布于2025-05-16
  • 在Oracle SQL中如何提取下划线前的子字符串?
    在Oracle SQL中如何提取下划线前的子字符串?
    [ 在oracle sql 解决方案: Explanation:SUBSTR function extracts a substring starting from the specified position (0) and continuing for a specified length.IN...
    编程 发布于2025-05-16
  • 用户本地时间格式及时区偏移显示指南
    用户本地时间格式及时区偏移显示指南
    在用户的语言环境格式中显示日期/时间,并使用时间偏移在向最终用户展示日期和时间时,以其localzone and格式显示它们至关重要。这确保了不同地理位置的清晰度和无缝用户体验。以下是使用JavaScript实现此目的的方法。方法:推荐方法是处理客户端的Javascript中的日期/时间格式化和时...
    编程 发布于2025-05-16
  • 如何解决AppEngine中“无法猜测文件类型,使用application/octet-stream...”错误?
    如何解决AppEngine中“无法猜测文件类型,使用application/octet-stream...”错误?
    appEngine静态文件mime type override ,静态文件处理程序有时可以覆盖正确的mime类型,在错误消息中导致错误消息:“无法猜测mimeType for for file for file for [File]。 application/application/octet...
    编程 发布于2025-05-16
  • Java中假唤醒真的会发生吗?
    Java中假唤醒真的会发生吗?
    在Java中的浪费唤醒:真实性或神话?在Java同步中伪装唤醒的概念已经是讨论的主题。尽管存在这种行为的潜力,但问题仍然存在:它们实际上是在实践中发生的吗? Linux的唤醒机制根据Wikipedia关于伪造唤醒的文章,linux实现了pthread_cond_wait()功能的Linux实现,利用...
    编程 发布于2025-05-16
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-05-16
  • 如何在Java的全屏独家模式下处理用户输入?
    如何在Java的全屏独家模式下处理用户输入?
    Handling User Input in Full Screen Exclusive Mode in JavaIntroductionWhen running a Java application in full screen exclusive mode, the usual event ha...
    编程 发布于2025-05-16
  • 如何在其容器中为DIV创建平滑的左右CSS动画?
    如何在其容器中为DIV创建平滑的左右CSS动画?
    通用CSS动画,用于左右运动 ,我们将探索创建一个通用的CSS动画,以向左和右移动DIV,从而到达其容器的边缘。该动画可以应用于具有绝对定位的任何div,无论其未知长度如何。问题:使用左直接导致瞬时消失 更加流畅的解决方案:混合转换和左 [并实现平稳的,线性的运动,我们介绍了线性的转换。这...
    编程 发布于2025-05-16
  • 如何在鼠标单击时编程选择DIV中的所有文本?
    如何在鼠标单击时编程选择DIV中的所有文本?
    在鼠标上选择div文本单击带有文本内容,用户如何使用单个鼠标单击单击div中的整个文本?这允许用户轻松拖放所选的文本或直接复制它。 在单个鼠标上单击的div元素中选择文本,您可以使用以下Javascript函数: function selecttext(canduterid){ if(do...
    编程 发布于2025-05-16

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3