Spring bean scopes
The scope of a bean specifies what kind of object has to be created by container for the bean defined.
We can define the scope of the bean while defining the bean in the spring configuration file.
Spring provides 5 scopes for a bean out of the box, we can also customize and create custom scope.
Types of bean scopes supported by Spring out of the box are as below
1. Singleton
Return a single bean instance per Spring container
2. Prototype
Return a new bean instance each time when requested for the container
3. Request
Return a single bean instance per HTTP request and Only valid in the context of a web-aware Spring ApplicationContext which means only in the web application.
4. Session
Return a single bean instance per HTTP session and Only valid in the context of a web-aware Spring ApplicationContext which means only in the web application.
5. GlobalSession
Return a single bean instance per global HTTP session
In portlet applications, session scope is considered as global session scope.
Hence only valid when used in a portlet context
Note:
By default, all the beans defined in spring will have singleton scope.
Singleton scope of a bean
As explained above, singleton bean will be only one instance for entire spring container, no matter how many times and in how many places we access it using context.getBean() method.
If we didn’t add any scope for the bean ,then Spring automatically makes that bean as Singleton.
Now Let us see Singleton bean with example
Create a class called Person as below
- package com.kb.beans.scope;
- public class Person {
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
package com.kb.beans.scope; public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Define the Person bean in the spring configuration file
- <?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"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd">
- <bean id="person" class="com.kb.beans.scope.Person">
- <property name="name" value="Name1"/>
- </bean>
- </beans>
<?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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <bean id="person" class="com.kb.beans.scope.Person"> <property name="name" value="Name1"/> </bean> </beans>
Note that,we have not defined any scope for the bean person in the above file,Even though the scope of a bean is Singleton because its default scope of a bean.
Create pom.xml as below
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>Spring</groupId>
- <artifactId>SpringCore</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>SpringCore</name>
- <url>http://maven.apache.org</url>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>4.2.4.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>4.2.4.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Spring</groupId> <artifactId>SpringCore</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>SpringCore</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
Let us test the same in the below class
- package com.kb.beans.scope;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class BeanScopeTest {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
- // Load Person object
- Person person1 = (Person) applicationContext.getBean("person");
- System.out.println("Name : " + person1.getName());
- Person person2 = (Person) applicationContext.getBean("person");
- System.out.println(person1 == person2);
- applicationContext.registerShutdownHook();
- }
- }
package com.kb.beans.scope; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanScopeTest { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); // Load Person object Person person1 = (Person) applicationContext.getBean("person"); System.out.println("Name : " + person1.getName()); Person person2 = (Person) applicationContext.getBean("person"); System.out.println(person1 == person2); applicationContext.registerShutdownHook(); } }
Run the above class and see the output
Even though we have accessed the bean 2 times using getBean() method. We can see that 2 instances are same.
When we compare 2 instances using == , it always checks the memory location of the 2 objects, and it is returning true which means both are same objects.
Now let’s modify the above program as below
- package com.kb.beans.scope;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class BeanScopeTest {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
- // Load Person object
- Person person1 = (Person) applicationContext.getBean("person");
- person1.setName("Name2");
- System.out.println("Name : " + person1.getName());
- Person person2 = (Person) applicationContext.getBean("person");
- System.out.println("Name : " + person2.getName());
- System.out.println(person1 == person2);
- applicationContext.registerShutdownHook();
- }
- }
package com.kb.beans.scope; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanScopeTest { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); // Load Person object Person person1 = (Person) applicationContext.getBean("person"); person1.setName("Name2"); System.out.println("Name : " + person1.getName()); Person person2 = (Person) applicationContext.getBean("person"); System.out.println("Name : " + person2.getName()); System.out.println(person1 == person2); applicationContext.registerShutdownHook(); } }
Here we have modified the person1 object to have a new name Name2
And loading person2 then accessing its name.
Now person2 also has a new name Name2 even though we have modified only person1
It clearly says that, both are one and the same instance.
Prototype scope of a bean
Prototype scope means container creates new instance every time we ask container to provide the bean using getBean() method.
Prototype scope must be defined explicitly
In simple words, each context.getBean() method returns a new object.
Now Let us see Prototype bean with example
Create a class called User as below
- package com.kb.beans.scope;
- public class User {
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
package com.kb.beans.scope; public class User { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Define the bean and make it as prototype explicitly
- <?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"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd">
- <bean id="person" class="com.kb.beans.scope.Person">
- <property name="name" value="Name1"/>
- </bean>
- <bean id="user" class="com.kb.beans.scope.User" scope="prototype">
- <property name="name" value="Name1"/>
- </bean>
- </beans>
<?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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <bean id="person" class="com.kb.beans.scope.Person"> <property name="name" value="Name1"/> </bean> <bean id="user" class="com.kb.beans.scope.User" scope="prototype"> <property name="name" value="Name1"/> </bean> </beans>
Now try to access the bean customer from the test class
- package com.kb.beans.scope;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class BeanScopeTest {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
- // prototype
- User user1 = (User) applicationContext.getBean("user");
- user1.setName("Name2");
- System.out.println("Name : " + user1.getName());
- User user2 = (User) applicationContext.getBean("user");
- System.out.println("Name : " + user2.getName());
- System.out.println(user1 == user2);
- applicationContext.registerShutdownHook();
- }
- }
package com.kb.beans.scope; import org.springframework.context.support.ClassPathXmlApplicationContext; public class BeanScopeTest { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); // prototype User user1 = (User) applicationContext.getBean("user"); user1.setName("Name2"); System.out.println("Name : " + user1.getName()); User user2 = (User) applicationContext.getBean("user"); System.out.println("Name : " + user2.getName()); System.out.println(user1 == user2); applicationContext.registerShutdownHook(); } }
Run the above program and see the output
Here we got the bean user1 by calling getBean() method
We changed its name to Name2 and then we accessed the bean user2 by calling getBean() method and its name is printed.
Note that, user2 has no affect of new Name this is because , the scope of User bean is set to prototype.
Also we compared user1 and user2 using == and it displayed as false, which means both are different objects.
So prototype scope always ensures that, each getBean() invocation returns the new object.
Hi ,
Can you please share some examples for bean scope Request and Session and GlobalSession.
Thanks in advance!