Spring框架是依赖注入的事实上的框架,在开发可扩展、弹性和安全的云原生环境中具有良好的记录。
在使用Spring Beans时,初学者经常会对Spring beans和它们的作用域感到有些困惑。
以下是我对Singleton和Prototype Bean作用域的简单示例进行阐述的尝试。
Singleton Bean作用域:正如其名称所示,作用域为Singleton的beans在Spring应用程序上下文中只有一个实例可用,然而值得注意的是,同一bean在Spring常量中可以具有不同的Bean名称下拥有多个实例。
这个想法与_Singleton设计模式_的概念有些不同,后者表示一旦将Java类设计为单例,JVM将在内存中只有单个实例可用。
Illustration 1.0 下面的插图显示了一个账户服务Spring bean,该bean可以具有不同的名称,同一服务在Spring上下文中可以存在两个不同的名称。
当我们在Java应用程序中引用一个singleton类时,该类只有一个实例可用,然而在Spring中,Singleton并不意味着上下文中只有一个该类型的实例,它可以有多个具有不同名称的该类型实例。
Prototype Bean作用域:当应用程序程序员将bean的作用域定义为Prototype时,这意味着每次有人请求引用一个bean时,Spring框架会返回全新的bean实例。Spring框架管理对象类型。
Illustration 1.1: 下面的插图定义了一个Prototype作用域的bean,并解释了每次我们请求Spring时,Spring都会提供所请求的bean的新实例。
为什么要让一个bean具有Prototype作用域?
Prototype作用域是为了避免两个线程在访问Singleton Bean时出现竞争条件。由于多线程环境的交错性质,这是一个经典的并发问题,操作的结果是不可预测的。因此,为了确保每个线程都获得自己的bean副本,开发人员希望确保每个线程都获得自己的副本。
什么是竞争条件?
以股票应用程序为例。股票价格每秒钟更新一次,并且用于为特定股票ID更新股票价格的代码是在并发上下文中编写的,这意味着可能有多个调用者试图更新股票X的价格。考虑一个一系列步骤的情况:
1.Mike试图将股票X的价格更新为110美元。2.Mike读取股票X的价格并将其增加到120美元。3.与此同时,在Mike将此写入主内存之前,他去了洗手间。4.Bob拿着咖啡回来,看到屏幕上的旧股票价值为105,他将股票X的价值更新为125美元。5.Mike回来,然后将股票X的值再次更新为120美元。6.由于这个构造,Mike想要对股票X进行的更新对Bob是不可见的,他再次覆盖了它。7.这是典型的竞争条件,我希望每个人都理解,就像Mike和Bob可以在这里被线程A和线程B替换一样,在并发环境中。
如果StockPrice被定义为Prototype作用域的bean,则每个线程都会获得其自己的StockPrice副本,它们不会互相干扰。但是,获得Stock价格的不同副本并不消除对给定股票的Stock价格更新进行同步的需要,它需要在一系列原子步骤中完成,但为了避免复杂性,我们可以略过这个讨论,以便理解Prototype Bean作用域。
Illustration 1.2: 下面的插图定义了一个Prototype作用域的bean,并解释了每个线程都会获得Prototype bean的新实例。
总结:
1.默认情况下,Spring bean的作用域是Singleton。2.Singleton作用域的bean在Spring应用程序上下文中可以具有不同的名称下的多个实例。3.Prototype bean是Spring框架提供的一个约定,每次请求时都会由框架提供bean的新实例。4.Prototype作用域的bean可以用于Singleton作用域的bean,但应该注意我们如何从上下文中获取该bean,因为如果将Prototype bean定义在Singleton bean内部,则Spring提供的原型bean实例只会有一个,这违背了其自身的目的。5.为了避免竞争条件,可以使用Prototype Bean作用域。