spring 单例bean和原型bean有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16058365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:52:55  来源:igfitidea点击:

What is difference between singleton and prototype bean?

springdependency-injection

提问by Amira

i'm new to spring and i read this :

我是春天的新手,我读到了这个:

Basically a bean has scopes which defines their existence on the application

Singleton: means single bean definition to a single object instance per Spring IOC container.

Prototype: means a single bean definition to any number of object instances.

基本上一个 bean 的作用域定义了它们在应用程序中的存在

单例:意味着单个 bean 定义到每个 Spring IOC 容器的单个对象实例。

原型:意味着对任意数量的对象实例的单个 bean 定义。

So What is the "object instance" .

那么什么是“对象实例”。

回答by LuckyLuke

Prototype scope= A new object is created each time it is injected/looked up. It will use new SomeClass()each time.

原型范围= 每次注入/查找时都会创建一个新对象。new SomeClass()每次都会用到。

Singleton scope= (Default)The same object is returned each time it is injected/looked up. Here it will instantiate one instance of SomeClassand then return it each time.

单例范围= (默认)每次注入/查找时都返回相同的对象。在这里它将实例化一个实例,SomeClass然后每次都返回它。

See also:

也可以看看:

回答by lordzuko

Let's just simply look this up through code.

让我们简单地通过代码查找一下。

Following is a TennisCoach Bean with default singletonScope

以下是具有默认singleton作用域的 TennisCoach Bean

@Component
@Scope("singleton")
public class TennisCoach implements Coach {

    public TennisCoach(){

    }

    @Autowired
    public void setFortuneService(FortuneService fortuneService) {
        this.fortuneService = fortuneService;
    }

    @Override
    public String getDailyWorkout() {
        return "Practice your backhand volley";
    }

    @Override
    public String getDailyFortune() {
        return "Tennis Coach says : "+fortuneService.getFortune();
    }

}

Following is a TennisCoach Bean with prototypescope

以下是具有原型范围的 TennisCoach Bean

@Component
@Scope("prototype")
public class TennisCoach implements Coach {

    public TennisCoach(){
        System.out.println(">> TennisCoach: inside default constructor");
    }

    @Autowired
    public void setFortuneService(FortuneService fortuneService) {
        System.out.println(">> Tennis Coach: inside setFortuneService");
        this.fortuneService = fortuneService;
    }

    @Override
    public String getDailyWorkout() {
        return "Practice your backhand volley";
    }

    @Override
    public String getDailyFortune() {
        return "Tennis Coach says : "+fortuneService.getFortune();
    }

}

Following is a Main class :

以下是一个主类:

public class AnnotationDemoApp {

    public static void main(String[] args) {


        // read spring config file
        ClassPathXmlApplicationContext context =
            new ClassPathXmlApplicationContext("applicationContext.xml");

       // get the bean from the spring container
       Coach theCoach = context.getBean("tennisCoach",Coach.class);
       Coach alphaCoach = context.getBean("tennisCoach",Coach.class);
       // call a method on the bean
       System.out.println("Are the two beans same :" + (theCoach==alphaCoach));

       System.out.println("theCoach : " + theCoach);
       System.out.println("alphaCoach: "+ alphaCoach);


       context.close()

    }
}

For singletonscope the output is :

对于单例范围,输出为:

Are the two beans same :true
theCoach : com.springdemo.TennisCoach@2a53142
alphaCoach: com.springdemo.TennisCoach@2a53142

For prototypescope the output is :

对于原型范围,输出为:

Are the two beans same :false
theCoach : com.springdemo.TennisCoach@1b37288
alphaCoach: com.springdemo.TennisCoach@1a57272

回答by shashi

Adding to the above..dont get confuse with the java singleton. according to JAVA spec singleton means only one instance of that bean will be created per JVM. but in spring singleton means one instance for that particular bean will be created per application context. so if your app has more than one context you can still have more than one instance for that bean.

添加到上面..不要与java单例混淆。根据 JAVA 规范单例意味着每个 JVM 只会创建该 bean 的一个实例。但在 spring 单例中意味着每个应用程序上下文将为该特定 bean 创建一个实例。因此,如果您的应用程序有多个上下文,您仍然可以为该 bean 拥有多个实例。

回答by guanabara

They are both creational design patterns.

它们都是创造型设计模式。

Singleton, will create a new instance in the first call, and return it in subsequent calls.

Singleton,将在第一次调用中创建一个新实例,并在后续调用中返回它。

Prototype will return a new instance each time.

Prototype 每次都会返回一个新实例。

回答by musibs

Singleton Scope:With Singleton scope, one and only one instance of a bean is created with the provided bean definition and for subsequent requests for the same bean, Spring container will return the same instance .

单例作用域:在单例作用域中,使用提供的 bean 定义创建一个且只有一个 bean 实例,对于同一 bean 的后续请求,Spring 容器将返回相同的实例。

From the Spring documentation:

从 Spring 文档:

.. when you define a bean definition and it is scoped as a singleton, the Spring IoC container creates exactly one instance of the object defined by that bean definition. This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object...

.. 当您定义一个 bean 定义并且它的作用域为单例时,Spring IoC 容器将创建该 bean 定义定义的对象的一个​​实例。该单个实例存储在此类单例 bean 的缓存中,并且对该命名 bean 的所有后续请求和引用都返回缓存对象...

Example: Lets say, we have defined a bean accountDaoas below:

示例:假设我们已经定义了一个 bean accountDao,如下所示:

<bean id="accountDao" class="" />

And another two beans, which uses this accountDaobean

还有另外两个bean,它使用这个accountDaobean

<bean id="someBean" ref="accountDao" /> 
<bean id="anotherBean" ref="accountDao" />

Spring will initially create accountDaobean and cache it. And then for someBeanas well as anotherBean, it will provide the same instance of accountDao.

Spring 最初会创建accountDaobean 并缓存它。然后 for someBeanas anotherBean,它将提供相同的accountDao.

Note:If no scope is specified with bean definition, Singleton is the default scope.

注意:如果 bean 定义中没有指定作用域,则单例是默认作用域。

Prototype Scope:For prototype scope, for each request for the bean, a new instance of the bean will be created and returned. This is similar to calling newoperator in java for a class.

原型作用域:对于原型作用域,对于 bean 的每个请求,都会创建并返回 bean 的一个新实例。这类似于在 Java 中为类调用new运算符。

Example: Lets say, we have defined a bean accountDaoas below:

示例:假设我们已经定义了一个 bean accountDao,如下所示:

<bean id="accountDao" class="" scope="prototype"/>

And another two beans, which uses this accountDaobean

还有另外两个bean,它使用这个accountDaobean

<bean id="someBean" ref="accountDao" /> 
<bean id="anotherBean" ref="accountDao" />

For someBean and anotherBean, Spring will return two separate instance of the accountDao object.

对于 someBean 和 anotherBean,Spring 将返回 accountDao 对象的两个单独实例。

One important difference is, for prototype scope, Spring does not manage the complete lifecycle of the bean, clean up needs to be done by the client code.

一个重要的区别是,对于原型作用域,Spring 不管理 bean 的完整生命周期,清理需要由客户端代码完成。

From the Spring documentation:

从 Spring 文档:

Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures, and otherwise assembles a prototype object, and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype bean(s) are holding.

Spring 不管理原型 bean 的完整生命周期:容器实例化、配置和以其他方式组装原型对象,并将其交给客户端,没有该原型实例的进一步记录。因此,尽管在所有对象上调用初始化生命周期回调方法,而不管范围如何,但在原型的情况下,不会调用配置的销毁生命周期回调。客户端代码必须清理原型范围的对象并释放原型 bean 持有的昂贵资源。

回答by MMKarami

I want to add some additional information that can help us to find out the meaning of "object instance" in mentioned sentences. This paragraph from Spring Doc try to define "object instance":

我想添加一些额外的信息,可以帮助我们找出上述句子中“对象实例”的含义。Spring Doc 中的这段尝试定义“对象实例”:

When you create a bean definition, you create a recipe for creating actualinstances of the class defined by that bean definition. The idea that a bean definition is a recipe is important, because it means that, as with a class, you can create many object instancesfrom a single recipe.

创建 bean 定义时,您创建了一个配方,用于创建由该 bean 定义定义的类的实际实例。bean 定义是一个配方的想法很重要,因为这意味着,与类一样,您可以从单个配方创建许多对象实例

Therefore, as mentioned in above section, each bean definition canor be considered as a Class(in terms of Object Oriented). According the data that you defined in it (such as scope, ...) this class (or bean definition) may have just one object instances (the singleton scope by only one shared instance) or any number of object instances(for example the prototype scope by creation of a new bean instance every time a request for that specific bean is made).

因此,如上一节所述,每个 bean 定义都可以被视为一个类(就面向对象而言)。根据您在其中定义的数据(例如范围,...),此类(或 bean 定义)可能只有一个对象实例(只有一个共享实例的单例范围)或任意数量的对象实例(例如原型作用域通过在每次对特定 bean 发出请求时创建一个新 bean 实例来实现)。

回答by Sumit Pokhrel

Prototype scope:A new object is created each time it is injected.
Singleton scope:The same object is returned each time it is injected.

原型作用域:每次注入时都会创建一个新对象。
单例作用域:每次注入都返回同一个对象。

Prototype scope is used for all beans that are stateful, while the singleton scope should be used for stateless beans. Let me explain with my example. Please copy and run it by yourself to get a clear understanding. Consider an interface Coach.

原型作用域用于所有有状态的 bean,而单例作用域应该用于无状态 bean。让我用我的例子来解释。请自行复制并运行,以获得清晰的理解。考虑一个界面教练。

public interface Coach {

    public String getDailyWorkout();

    public String getDailyFortune();

}

We have another class called TrackCoach which implements Coach.

我们有另一个名为 TrackCoach 的类,它实现了 Coach。

public class TrackCoach implements Coach {

    private FortuneService fortuneService;


    public TrackCoach(FortuneService fortuneService) {
        this.fortuneService = fortuneService;
    }

    @Override
    public String getDailyWorkout() {
        return "Run a hard 5k";
    }

    @Override
    public String getDailyFortune() {
        return "Just Do it: " + fortuneService.getFortune();
    }    
}

Now there is a FortuneService interface.

现在有一个 FortuneService 接口。

public interface FortuneService {

    public String getFortune();

}

It is implemented by our class HappyFortuneService.

它由我们的HappyFortuneService 类实现。

public class HappyFortuneService implements FortuneService {

    @Override
    public String getFortune() {
        return "Today is your lucky day!";
    }

}

Let's wire the two classes and inject an object bean of one class into another using Xml. Let's perform dependency injection. Note that we can do this using java annotation too.

让我们连接这两个类,并使用 Xml 将一个类的对象 bean 注入到另一个类中。让我们执行依赖注入。请注意,我们也可以使用 java 注释来做到这一点。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">


    <!-- Define your beans here -->

    <!--  define the dependency  -->
    <bean id = "myFortuneService"
        class = "com.luv2code.springdemo.HappyFortuneService">
    </bean>

    <bean id = "myCoach"
        class = "com.luv2code.springdemo.TrackCoach"
        scope = "singleton">


        <!-- set up construction injection -->
        <constructor-arg ref = "myFortuneService" />
    </bean>

</beans>

Notice that scope = singleton.

请注意scope = singleton

Now let's define our BeanScopeDemoApp, which has our main method.

现在让我们定义我们的 BeanScopeDemoApp,它有我们的主要方法。

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanScopeDemoApp {

    public static void main(String[] args) {

        // load the spring configuration file 
        ClassPathXmlApplicationContext context = 
                new ClassPathXmlApplicationContext("beanScope-applicationContext.xml");

        // retrieve bean from spring container 
        Coach theCoach = context.getBean("myCoach", Coach.class);

        Coach alphaCoach = context.getBean("myCoach", Coach.class);

        // check if they are the same 
        boolean result = (theCoach == alphaCoach);

        // print out the results 
        System.out.println("\nPointing to the same object: " + result);

        System.out.println("\nMemory location for theCoach: " + theCoach);

        System.out.println("\nMemory location for alphaCoach: " + alphaCoach +"\n");

        // close the context 
        context.close();
    }

}

Once you run the above code, you will see the following results:

运行上述代码后,您将看到以下结果:

Pointing to the same object: true

Memory location for theCoach: com.luv2code.springdemo.TrackCoach@16515bb7

Memory location for alphaCoach: com.luv2code.springdemo.TrackCoach@16515bb7

It's pointing the same object and occupies the same memory location after calling it twice. Now let's change the scope = prototypein our Xml file, save it and run the BeanScopeDemoApp again.
You will see the following results:

它指向同一个对象并在调用它两次后占用相同的内存位置。现在让我们更改scope = prototypeXml 文件中的 ,保存并再次运行 BeanScopeDemoApp。
您将看到以下结果:

Pointing to the same object: false

Memory location for theCoach: com.luv2code.springdemo.TrackCoach@6d4d203d

Memory location for alphaCoach: com.luv2code.springdemo.TrackCoach@627fbcda

It's pointing the different object and occupies the different memory locations after calling it twice. This would be a graphical illustration of what i have just said. enter image description hereenter image description here

它指向不同的对象并在调用它两次后占用不同的内存位置。这将是我刚才所说内容的图形说明。 在此处输入图片说明在此处输入图片说明

回答by vijay anirudh

  1. Singleton scope is default.
  2. Singleton beans are created during initialization of app context and same bean is returned always.
  3. Prototype bean is created when ever it is called. Each time it is called we get a new object.
  1. 单例范围是默认的。
  2. 单例 bean 是在应用程序上下文初始化期间创建的,并且始终返回相同的 bean。
  3. 原型 bean 在被调用时被创建。每次调用它时,我们都会得到一个新对象。

Note : Bean with any scope will be created if it is referred by other beans and called using Application context.

注意:如果被其他 bean 引用并使用应用程序上下文调用,则将创建具有任何范围的 Bean。

Example code to check this.

用于检查这一点的示例代码。

public class PrototypeClass {

        PrototypeClass()
        {
            System.out.println("prototype class is created"+this.toString());
        }

    }

This will print the relevant text when constructor is invoked.

这将在调用构造函数时打印相关文本。

for the below code

对于下面的代码

for(int i=0;i<10;i++) {
   PrototypeClass pct= (PrototypeClass) context.getBean("protoClass");
}

prototype class is createdSpring.PrototypeClass@29774679 prototype class is createdSpring.PrototypeClass@3ffc5af1 prototype class is createdSpring.PrototypeClass@5e5792a0 prototype class is createdSpring.PrototypeClass@26653222 prototype class is createdSpring.PrototypeClass@3532ec19 prototype class is createdSpring.PrototypeClass@68c4039c prototype class is createdSpring.PrototypeClass@ae45eb6 prototype class is createdSpring.PrototypeClass@59f99ea prototype class is createdSpring.PrototypeClass@27efef64 prototype class is createdSpring.PrototypeClass@6f7fd0e6 prototype class is createdSpring.PrototypeClass@47c62251

原型类创建Spring.PrototypeClass@29774679 原型类创建Spring.PrototypeClass@3ffc5af1 原型类创建Spring.PrototypeClass@5e5792a0 原型类创建Spring.PrototypeClass@26653222 原型类创建Spring.PrototypeClass@3532ec19 PrototypeClass@3532ec19 PrototypeClass@3532ec19 PrototypeClass@36Spring创建Spring.PrototypeClass@ae45eb6原型类创建Spring.PrototypeClass@59f99ea原型类创建Spring.PrototypeClass@27efef64原型类创建Spring.PrototypeClass@6f7fd0e6原型类创建Spring.PrototypeClass@47c62251

Bean definition is

Bean定义是

<bean id="protoClass" class="Spring.PrototypeClass" scope="prototype</bean>

Now I changed the scope in bean definition to singleton . Constructor is called only once during initialization of context. Next I removed the scope attribute and observed same behavior as singleton.

现在我将 bean 定义中的范围更改为 singleton 。构造函数在上下文初始化期间仅被调用一次。接下来,我删除了 scope 属性并观察到与单例相同的行为。

回答by Kislay Sinha

Singleton is same instance across application

单例是跨应用程序的相同实例

Prototype is new instance for every new request of getBean

原型是 getBean 的每个新请求的新实例