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 def
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 .
From the Spring documentation:
.. 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...
Example:
Lets say, we have defined a bean accountDao
as below:
<bean id="accountDao" class="" />
And another two beans, which uses this accountDao
bean
<bean id="someBean" ref="accountDao" />
<bean id="anotherBean" ref="accountDao" />
Spring will initially create accountDao
bean and cache it. And then for someBean
as well as anotherBean
, it will provide the same instance of accountDao
.
Note: If no scope is specified with bean definition, Singleton is the default scope.
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 new operator in java for a class.
Example:
Lets say, we have defined a bean accountDao
as below:
<bean id="accountDao" class="" scope="prototype"/>
And another two beans, which uses this accountDao
bean
<bean id="someBean" ref="accountDao" />
<bean id="anotherBean" ref="accountDao" />
For someBean and anotherBean, Spring will return two separate instance of the accountDao object.
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.
From the Spring documentation:
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.
They are both creational design patterns.
Singleton, will create a new instance in the first call, and return it in subsequent calls.
Prototype will return a new instance each time.
Let's 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
Singleton is same instance across application
Prototype is new instance for every new request of getBean
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":
When you create a bean definition, you create a recipe for creating actual instances 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 instances from a single recipe.
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).
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.