What is difference between singleton and prototype

2019-01-16 16:18发布

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.

So What is the "object instance" .

12条回答
小情绪 Triste *
2楼-- · 2019-01-16 16:43

Let'just simply look this up through Code.

Following is a TennisCoach Bean with default singleton Scope

@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 prototype scope

@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 singleton scope the output is :

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

For prototype scope the output is :

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

Hope this answers your question. :D

查看更多
手持菜刀,她持情操
3楼-- · 2019-01-16 16:44

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

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

See also:

查看更多
爱情/是我丢掉的垃圾
4楼-- · 2019-01-16 16:46

Singleton: If scope is set to 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.

Prototype: If scope is set to prototype, the Spring IoC container creates new bean instance of the object every time a request for that specific bean is made. As a rule, use the prototype scope for all state-full beans and the singleton scope for stateless beans.

查看更多
冷血范
5楼-- · 2019-01-16 16:47

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.

public interface Coach {

    public String getDailyWorkout();

    public String getDailyFortune();

}

We have another class called TrackCoach which implements 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.

public interface FortuneService {

    public String getFortune();

}

It is implemented by our class 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 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.

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

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 = prototype in our Xml file, save it and run the BeanScopeDemoApp again.
You will see the following results:

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 here enter image description here

查看更多
看我几分像从前
6楼-- · 2019-01-16 16:47
  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.

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

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

Bean definition is

<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.

查看更多
太酷不给撩
7楼-- · 2019-01-16 16:48

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.

查看更多
登录 后发表回答