【问题标题】:If singleton is bad!! why spring bean are singletone by default [duplicate]如果单身不好!为什么spring bean默认是单调的[重复]
【发布时间】:2017-01-06 10:09:03
【问题描述】:

What is so bad about singletons?

已经解释得很清楚,单例设计模式违反了多个最佳实践。那为什么spring beans默认是单例的呢?这样的设计不会间接导致同样的违规吗?

【问题讨论】:

  • 强制它是单例的type 和决定向所有消费者提供单个实例的框架 之间存在区别。例如,前者使测试变得困难,而后者则不然。
  • 您好 Niru,此信息可在此处找到:stackoverflow.com/questions/2637864/…
  • 单身人士还不错。在不必要的时候使用它们是不好的。
  • 基本上是 Jens 在他的回答中提出的......
  • 这只是 Spring 选择错误的名称。 Spring 的@Singleton 有效地遵循了“Just create one”模式。另见 a.o. butunclebob.com/ArticleS.UncleBob.SingletonVsJustCreateOne。 Java EE 为这些 bean 提供了更好的范围名称:@ApplicationScoped。

标签: java spring


【解决方案1】:

单例模式和弹簧单例几乎没有共同之处。实际上唯一的可能是:

生产中运行时只有一个实例

让我们从您链接到的答案中查看该模式的批评者:

它们通常用作全局实例,为什么这么糟糕?因为您在代码中隐藏了应用程序的依赖项,而不是通过接口公开它们。使某些东西全局化以避免传递它是一种代码味道。

在 Spring 中,您正在做完全相反的事情。你只是说:“我需要其中之一,而不关心它来自哪里。”

它们违反了单一责任原则:因为它们控制着自己的创建和生命周期。

再次重申:Spring 正好相反:您编写一个普通的 pojo,然后在 Spring 配置中配置它应该具有的生命周期。

它们本质上会导致代码紧密耦合。在许多情况下,这使得在测试中伪装它们变得相当困难。

使用 Spring,没有什么能阻止您为每个测试使用不同的实例。

它们在应用程序的整个生命周期内都携带状态。测试的另一个打击,因为您最终可能会遇到需要订购测试的情况,这对于单元测试来说是一个很大的禁忌。为什么?因为每个单元测试都应该相互独立。

是的,它们可以在应用程序的整个生命周期内携带状态,但由于您可以选择更改生命周期或测试(或应用程序的不同实例)中的实现,因此测试彼此保持独立。

所有这些实际上并不是 Spring 特有的,而是可能适用于所有成熟的依赖注入框架,即使您选择手动执行也是如此。

【讨论】:

    【解决方案2】:

    Spring Singleton 并不是我们从 GOF 设计模式中知道的真正的 Singleton。 它们会给你那种感觉,因为 IoC 容器(Bean Factory)会有一个 bean。

    这意味着您可以实例化一个为它创建的单例 bean 的类。

    您还可以拥有 2 个来自同一类的单例 bean。

    所以,'singularity' 是 bean factory 中 bean 的概念,而不是类。

    例子:

    @Configuration
    public class AppConfig {
    
        @Bean(name = "a")
        public MyBeanClass a() {
            return new MyBeanClass();
        }
    
       @Bean(name = "b")
        public MyBeanClass b() {
            return new MyBeanClass();
        }
    }
    

    因此,您将拥有 2 个 MyBeanClass 类的单例 bean。而且 MyBeanClass 不是设计模式的单例。

    【讨论】:

      猜你喜欢
      • 2019-06-11
      • 2010-10-15
      • 1970-01-01
      • 2011-08-27
      • 1970-01-01
      • 1970-01-01
      • 2010-10-23
      相关资源
      最近更新 更多