如果单例模式不好,为什么Spring Bean默认是单例的?

6

单例模式有何不好之处?

清楚地解释了单例设计模式违反了多个最佳实践。那么为什么Spring的bean默认是单例的呢?这种设计是否会间接导致相同的违规行为?


10
一个"类型"强制成为单例,和一个框架"决定为所有用户提供单个实例"之间有所不同。例如,前者使测试变得困难 - 后者则不会。 - Jon Skeet
3
嗨Niru,这个信息可以在这里找到:https://dev59.com/XXE85IYBdhLWcg3wvGER - pandaadb
3
单例模式本身不是坏的,但在不必要的情况下使用它们才是问题所在。 - Alexandru Severin
3
基本上就是Jens在他的回答中所说的内容。 - Jon Skeet
2
这只是Spring不太恰当的命名而已。Spring的@Singleton实际上遵循“只创建一个”的模式。另请参见http://butunclebob.com/ArticleS.UncleBob.SingletonVsJustCreateOne。对于这些bean,Java EE有更好的范围名称:@ApplicationScoped - BalusC
显示剩余8条评论
2个回答

16
单例模式和Spring单例很少有共同点,实际上仅有的一点可能是:在生产环境中仅有一个实例。 让我们看一下从链接答案中对该模式进行的批评: 它们通常被用作全局实例,为什么这样不好?因为您将应用程序的依赖关系隐藏在代码中,而不是通过接口公开它们。将某个东西设置为全局变量以避免传递它是一种“异味代码”。 使用Spring时,您正在做完全相反的事情。 您只需要说:“我需要其中之一,而不关心它来自哪里。” 它们违反了单一责任原则:由于它们控制自己的创建和生命周期。 再次强调:Spring恰恰相反:您编写一个普通的POJO,然后在Spring配置中配置它的生命周期。 它们本质上会导致代码紧密耦合。这使得在许多情况下很难对其进行伪造测试。 使用Spring,您可以在每个测试中使用不同的实例,没有任何限制。 它们在整个应用程序的生命周期中携带状态。这对测试造成了打击,因为您可能会出现需要按顺序进行测试的情况,这对于单元测试来说是绝对不行的。为什么?因为每个单元测试都应该独立于其他测试。 是的,它们可以在整个应用程序的生命周期中携带状态,但由于您可以选择更改测试中的生命周期或实现(或应用程序的不同实例),因此测试保持彼此独立。 所有这些真的不特定于Spring,但对于可能所有成熟的依赖注入框架来说都是正确的,即使您选择手动执行也是如此。

6

Spring单例并不是我们从GOF设计模式中所知道的真正的单例。它们给你这种感觉,因为IoC容器(Bean工厂)中只有一个bean。

也就是说,你可以实例化一个类,为它创建一个单例bean。

你还可以从同一类中拥有2个单例bean。

因此,“单一性”在于bean工厂中的bean概念,而不是一个类。

例如:

@Configuration
public class AppConfig {

    @Bean(name = "a")
    public MyBeanClass a() {
        return new MyBeanClass();
    }

   @Bean(name = "b")
    public MyBeanClass b() {
        return new MyBeanClass();
    }
}

所以,您将拥有两个MyBeanClass类的单例bean。而MyBeanClass不是单例设计模式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接