Spring Bean Scopes

By Arvind Rai, March 12, 2023
This page will walk through Spring bean scope example using @Scope annotation and XML configuration. Using scoped proxy, we will understand how to inject short lived bean scope to long lived bean scope. The Scopes provided by Spring are singleton, prototype, request, session, globalSession and application. The singleton and prototype scopes are Spring's standard scope and can be used in standalone as well as web application. The other bean scope that are request, session, globalSession and application are valid only in web aware application. globalSession scope is specific to portlet application. Here on this page, we will use XML configuration as well as @Scope annotation to provide the examples of Spring bean scopes.

1. Spring Bean Scopes

As of Spring 4.2 release, there are following bean scopes.
1. singleton
2. prototype
3. request
4. session
5. globalSession
6. application

1.1 singleton Scope

singleton scope is default scope of a bean in spring container. In this scope, spring creates only one instance of the bean and it is served for every request for that bean from cache within the container. Only one instance of bean per bean id is created in singleton scope. If two beans with different id but of same class is there in singleton scope, then two instances will be created of that class and in terms of bean id, only one instance of bean is created. In singleton scope, one instance of bean is created by spring container and put in cache. In spring bean dependency, singleton scoped bean is injected from cache as shared bean. singleton scope is limited to spring container. This differs from the Java Singleton Design Pattern which is based on per ClassLoader. In spring, singleton is per container and per bean. singleton scope is standard scope in spring and is valid in standalone as well as web applications. singleton scope is used for stateless beans.

1.2 prototype Scope

In spring prototype scope, spring container creates new instance of bean for each and every request for that bean. In spring bean dependency, prototype scoped bean is served by creating new instance of bean for each and every bean dependency. prototype scope is used for stateful beans. Spring container does not maintain the full record of prototype scoped beans. After instantiating bean and submitting it to client, spring container does not maintain the record. So to release the resources held by prototype scoped bean, client should implement custom bean post-processor. prototype scope is spring standard scope and can be used in standalone as well as web application of spring.

1.3 request Scope

In spring, request scoped bean is used in HTTP request life-cycle. For each and every HTTP request, new instance of bean is created and is alive for complete HTTP request life-cycle. request scoped bean cannot be used with spring standalone application, it can be used only in web application. In one HTTP request, only one instance of request scoped bean is created and in other subsequent request another instance of bean is created per request. The life cycle of request scoped bean starts and ends within the life cycle of HTTP request. Within HTTP request, the changes done in request scoped bean does not affect the other HTTP request. Once HTTP request is completed, the instance of request scoped bean is also destroyed. We can understand request scoped bean as per HTTP request and per bean id.

1.4 session Scope

session scoped bean in spring is used in HTTP Session of web application. For each and every HTTP session, only one instance of bean is created and is alive for complete HTTP session life cycle. The life cycle of session scoped bean is within the life cycle of HTTP session life cycle. If HTTP session is discarded, the session scoped bean created within HTTP session is also discarded. Two parallel HTTP sessions do not share the changes done in session scoped bean instances. Once the HTTP session is out, the session scoped bean instance is also destroyed created within that HTTP session. session scoped bean is per HTTP session and per bean id.

1.5 globalSession Scope

globalSession scoped bean is used in portlet based spring web application. Only one instance of globalSession scoped bean is created for life cycle of global HTTP session. Global HTTP session is the HTTP session that is shared among all portlets to make a single portlet web application. globalSession scoped bean instance has the life cycle within global HTTP session life cycle. The changes done in globalSession scoped bean instance does not affect to another parallel global HTTP session. Once the global HTTP session is out, the instance of globalSession scoped bean is also destroyed. globalSession scoped bean is per global HTTP session and per bean id.

1.6 application Scope

application scope has been introduced in Spring 4.0. Only one instance of bean is created for the complete life cycle of ServletContext. The instance of application scoped bean is stored as ServletContext attribute. application scoped bean is used in spring web application. This scope is similar to singleton scope with one difference that application scope is ServletContext specific and singleton scope is spring ApplicationContext specific.

2. Prototype Scope using XML

To understand prototype scope, find the code snippet. In spring <bean> tag, there is an attribute as scope which assigns the scope value as prototype.
    <bean id="address" class="com.concretepage.bean.Address" scope="prototype">
      <constructor-arg name="city" value="Varanasi"/>
     </bean>  
Find the example for prototype scope. We are creating one bean in prototype scope and being injected to two other beans.
spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address" class="com.concretepage.bean.Address" scope="prototype">
      <constructor-arg name="city" value="Varanasi"/>
     </bean> 
    <bean id="teacher" class="com.concretepage.bean.Teacher">
      <property name="teachAddress" ref="address"/>
    </bean>
    <bean id="student" class="com.concretepage.bean.Student">
      <property name="stAddress" ref="address"/>
    </bean>
</beans> 
Address.java
package com.concretepage.bean;
public class Address {
	private String city;
	public Address(String city) {
		this.city = city;
		System.out.println("My city:" + city);
	}
        public String getCity() {
		return city;
	}
} 
Student.java
package com.concretepage.bean;
public class Student {
	private Address stAddress;
	public Address getStAddress() {
		return stAddress;
	}
	public void setStAddress(Address stAddress) {
		this.stAddress = stAddress;
	}
} 
Teacher.java
package com.concretepage.bean;
public class Teacher {
	private Address teachAddress;
	public Address getTeachAddress() {
		return teachAddress;
	}
	public void setTeachAddress(Address teachAddress) {
		this.teachAddress = teachAddress;
	}
} 
SpringDemo.java
package com.concretepage;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo {
	public static void main(String[] args) {
		 ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
	}
} 
build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'
archivesBaseName = 'SpringDemo'
version = '1' 
repositories {
    mavenCentral()
}
dependencies {
    compile 'org.springframework.boot:spring-boot-starter:1.2.7.RELEASE'
}  
In the output we will observe that the bean scoped as prototype has been instantiated two times. Find the output.
My city:Varanasi
My city:Varanasi

3. Singleton Scope using XML

In singleton bean scope, we need to assign singleton value to the attribute scope.
    <bean id="address" class="com.concretepage.bean.Address" scope="singleton">
      <constructor-arg name="city" value="Varanasi"/>
     </bean>  
For the example, do changes as above in spring-config.xml and then run the code. In the output we will observe that the bean scoped as singleton has been instantiated only one time. Find the output.
My city:Varanasi

4. Prototype Scope using @Scope Annotation

Spring provides @Scope annotation to keep the bean in desired scope. Just annotate the class with this annotation and provide the bean scope value. Find the code snippet for how to use @Scope annotation with prototype scope.
@Scope("prototype")
public class Address {}  
Find the code.
Address.java
package com.concretepage.bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Scope("prototype")
@Component
public class Address {
	private String city = "Varanasi";
	public Address() {
		System.out.println("My city:" + city);
	}
        public String getCity() {
		return city;
	}
} 

Student.java
package com.concretepage.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Student {
	@Autowired
	private Address stAddress;
	public Address getStAddress() {
		return stAddress;
	}
} 

Teacher.java
package com.concretepage.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Teacher {
	@Autowired
	private Address teachAddress;
	public Address getTeachAddress() {
		return teachAddress;
	}
} 

AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages="com.concretepage.bean")
public class AppConfig {
} 

SpringDemo.java
package com.concretepage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringDemo {
	public static void main(String[] args) {
	       AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
	       ctx.register(AppConfig.class);
	       ctx.refresh();
	}
} 


5. Singleton Scope using @Scope Annotation

To use singleton scope with @Scope annotation, we need to do changes as below. Just change the scope value as singleton.
@Scope("singleton")
public class Address {}  

6. Scoped Proxy : Scoped Beans as Dependencies

In the case when we inject short lived bean (like request, session scope) in long lived bean (like singleton and prototype) then we need to use AOP proxy in place of scoped bean. It means we need to inject proxy object.

1. In case of XML, we can use spring tag <aop:scoped-proxy/> for short lived scope bean.
2. In case of @Scope annotation, spring provides attribute as proxyMode which has the values as TARGET_CLASS, NO, INTERFACES and DEFAULT.

7. Request Scope using XML

Find the code snippet for how to use request scope using XML.
   <bean id="address" class="com.concretepage.bean.Address" scope="request">
      <constructor-arg name="city" value="Varanasi"/>
      <aop:scoped-proxy/>
   </bean>  
We need to use <;aop:scoped-proxy/>; tag when we are injecting our short lived bean to long lived bean. In our example, we are injecting request scoped bean to singleton scoped bean.
dispatcher-servlet.xml
<?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:mvc="http://www.springframework.org/schema/mvc"
   xmlns:aop="http://www.springframework.org/schema/aop"
   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 http://www.springframework.org/schema/mvc
   http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop.xsd"">

   <mvc:annotation-driven />
   <context:component-scan base-package="com.concretepage.controller" />
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/WEB-INF/pages/"/>
       <property name="suffix" value=".jsp"/> 
   </bean>
   <bean id="address" class="com.concretepage.bean.Address" scope="request">
      <constructor-arg name="city" value="Varanasi"/>
      <aop:scoped-proxy/>
   </bean>
   <bean id="teacher" class="com.concretepage.bean.Teacher">
      <property name="teachAddress" ref="address"/>
   </bean>
</beans> 
HelloController.java
package com.concretepage.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.concretepage.bean.Teacher;
@Controller
@RequestMapping("/hello")
public class HelloController {
	@Autowired
	private Teacher teacher;
	@RequestMapping
        public ModelAndView hello(ModelAndView  modelAndView) {
	  modelAndView.setViewName("hello");
	  modelAndView.addObject("city", teacher.getTeachAddress().getCity());
	  return modelAndView;
        }
}  
web.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd"
    version="3.0">
	<display-name>Spring MVC Application</display-name>
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
</web-app> 
hello.jsp
<html>
<head><title>Hello Spring Scopes</title></head>
<body>
	My City: ${city}
</body>
</html> 

build.gradle
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web:1.2.7.RELEASE'    
    compile 'jstl:jstl:1.2'    
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat:1.2.7.RELEASE'
}  
To run the application, use the URL http://localhost:8080/spring-demo-1/hello. We will observe in the output that for each and every request, bean is being instantiated.
My city:Varanasi
 

8. Session Scope using XML

To use session scope using XML, just change the scope value as session.
   <bean id="address" class="com.concretepage.bean.Address" scope="session">
      <constructor-arg name="city" value="Varanasi"/>
      <aop:scoped-proxy/>
   </bean>  
We will observe in the output that for one session, bean is being instantiated only one time.

9. Global Session Scope using XML

To use global session scope using XML, just change the scope value as globalSession.
   <bean id="address" class="com.concretepage.bean.Address" scope="globalSession">
      <constructor-arg name="city" value="Varanasi"/>
      <aop:scoped-proxy/>
   </bean>  

10. Application Scope using XML

To use application scope using XML, just change the scope value as application.
   <bean id="address" class="com.concretepage.bean.Address" scope="application">
      <constructor-arg name="city" value="Varanasi"/>
      <aop:scoped-proxy/>
   </bean>  

11. Request Scope using @Scope Annotation

To use request scope using @Scope annotation, we can do as follows.
@Scope(value="request", proxyMode =ScopedProxyMode.TARGET_CLASS)
public class Address {} 
@Scope annotation has the attribute proxyMode that is used to create AOP proxy of the bean. We need to do it when we are injecting short lived bean scope to long lived bean scope. In our example, we are injecting request scope bean to singleton scope bean.
Find the code.
Address.java
package com.concretepage.bean;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
@Scope(value="session", proxyMode =ScopedProxyMode.TARGET_CLASS)
@Component
public class Address {
	private String city = "Varanasi";
	public Address() {
		System.out.println("My city:" + city);
	}
        public String getCity() {
		return city;
	}
} 
Teacher.java
package com.concretepage.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Teacher {
	@Autowired
	private Address teachAddress;
	public Address getTeachAddress() {
		return teachAddress;
	}
} 
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@ComponentScan(basePackages="com.concretepage")
@EnableWebMvc
public class AppConfig {
    @Bean  
    public InternalResourceViewResolver viewResolver() {  
	InternalResourceViewResolver resolver = new InternalResourceViewResolver();  
        resolver.setPrefix("/WEB-INF/pages/");  
        resolver.setSuffix(".jsp");
        return resolver;  
    }
} 
WebAppInitializer.java
package com.concretepage;
import javax.servlet.ServletContext;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRegistration.Dynamic;  
import org.springframework.web.WebApplicationInitializer;  
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;  
import org.springframework.web.servlet.DispatcherServlet;  
public class WebAppInitializer implements WebApplicationInitializer {
	public void onStartup(ServletContext servletContext) throws ServletException {  
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();  
        ctx.register(AppConfig.class);  
        ctx.setServletContext(servletContext);    
        Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));  
        dynamic.addMapping("/");  
        dynamic.setLoadOnStartup(1);  
   }  
} 

12. Session Scope using @Scope Annotation

To use session scope using @Scope annotation, use the value as session.
@Scope(value="session", proxyMode =ScopedProxyMode.TARGET_CLASS)
public class Address {}  

13. Global Session Scope using @Scope Annotation

To use global session scope using @Scope annotation, use the value as globalSession.
@Scope(value="globalSession", proxyMode =ScopedProxyMode.TARGET_CLASS)
public class Address {}  

14. Application Scope using @Scope Annotation

To use application scope using @Scope annotation, use the value as application.
@Scope(value="application", proxyMode =ScopedProxyMode.TARGET_CLASS)
public class Address {}  

15. Reference

Bean scopes

16. Download Complete Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us