Comprehensive Guide to Spring Bean Scopes: From Singleton to Request-Level Lifecycle Management

Dec 08, 2025 · Programming · 15 views · 7.8

Keywords: Spring Bean | Scope | Singleton | Prototype | Request | Session | IoC Container

Abstract: This article provides an in-depth exploration of the five bean scopes in the Spring Framework: singleton, prototype, request, session, and global session. Through comparative analysis of different scopes' lifecycles, use cases, and configuration methods, it helps developers choose appropriate bean management strategies based on application requirements. The article combines code examples and practical scenarios to explain the behavioral characteristics of each scope and their implementation mechanisms in the Spring IoC container.

Overview of Spring Bean Scopes

In the Spring Framework, bean scope defines the lifecycle and visibility boundaries of bean instances within the Spring IoC container. Scope determines how the container creates, manages, and destroys bean instances, forming a crucial component of Spring's dependency injection mechanism. Proper understanding and utilization of bean scopes are essential for building efficient and maintainable Spring applications.

Detailed Explanation of Five Bean Scopes

1. Singleton Scope

Singleton is the default scope for Spring beans. In this scope, the Spring IoC container creates exactly one instance per bean definition. This instance is stored in the container's singleton cache, and all subsequent requests for that bean return the same cached instance.

Configuration example:

<bean id="exampleBean" class="com.example.ExampleBean" scope="singleton">
    <property name="dependency" ref="someDependency"/>
</bean>

Or using annotation approach:

@Component
@Scope("singleton")
public class ExampleBean {
    // Bean implementation
}

Singleton scope is suitable for stateless beans such as service layer components and data access objects, which typically don't need to maintain request- or session-specific state.

2. Prototype Scope

Prototype scope is the opposite of singleton - a new instance is created each time the bean is requested from the container. The Spring container does not cache prototype bean instances, generating new objects with every getBean() call or dependency injection reference.

Configuration example:

<bean id="customerInfoController" class="com.action.Controller" scope="prototype">
    <property name="accountDao" ref="accountDao"/>
    <property name="utilityDao" ref="utilityDao"/>
    <property name="account_usageDao" ref="account_usageDao"/>
</bean>

Prototype scope is appropriate for beans that need to maintain state, particularly those requiring independent instances for each usage. Note that the Spring container only handles prototype bean initialization, not destruction, requiring developers to manage resource cleanup.

3. Request Scope

Request scope confines a bean's lifecycle to a single HTTP request. Each HTTP request creates an independent bean instance, which is destroyed when the request completes. This scope is only valid in web-aware Spring ApplicationContext environments.

Configuration example (annotation-based):

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestScopedBean {
    private String requestId;
    
    @PostConstruct
    public void init() {
        this.requestId = UUID.randomUUID().toString();
    }
    
    public String getRequestId() {
        return requestId;
    }
}

Request scope is commonly used for scenarios requiring request-specific state tracking, such as request-level data holders or request-specific configurations.

4. Session Scope

Session scope binds bean instances to the lifecycle of an HTTP session. Each user session corresponds to one bean instance, instantiated when the session is created and cleaned up when the session is destroyed. This also requires web-aware ApplicationContext support.

Configuration example:

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserPreferences {
    private String theme = "default";
    private Locale locale = Locale.getDefault();
    
    // Getter and setter methods
    public String getTheme() {
        return theme;
    }
    
    public void setTheme(String theme) {
        this.theme = theme;
    }
    
    public Locale getLocale() {
        return locale;
    }
    
    public void setLocale(Locale locale) {
        this.locale = locale;
    }
}

Session scope is suitable for storing user-specific data such as user preferences, shopping cart contents, etc.

5. Global Session Scope

Global session scope is a concept from the Portlet specification, binding bean instances to global HTTP sessions. In standard Servlet environments, it behaves identically to session scope; in Portlet environments, it spans sessions across multiple portlets. This scope also requires web-aware ApplicationContext.

Configuration example:

<bean id="globalPreferences" class="com.example.GlobalPreferences" scope="globalSession">
    <!-- Bean configuration -->
</bean>

Global session scope is primarily used in Portlet applications for sharing session data across multiple portlets.

Scope Selection and Practical Recommendations

Comparative Analysis of Scopes

Different scopes exhibit significant variations in memory usage, performance, and thread safety:

Scope Proxy Mechanism

When injecting shorter-lived scopes (e.g., request, session) into longer-lived beans (e.g., singleton), scope proxies are necessary. Spring configures proxy modes through ScopedProxyMode:

@Autowired
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
private RequestScopedBean requestBean;

The proxy mechanism ensures that each method invocation retrieves the correct scoped instance.

Best Practices

  1. Default to singleton scope unless other scopes are explicitly required
  2. For stateful beans, select appropriate scopes based on state lifecycle requirements
  3. In web applications, judiciously use request and session scopes for managing request and session data
  4. Pay attention to proxy configuration when combining scopes to avoid scope mismatch issues
  5. For prototype beans, ensure proper resource release management

Advanced Configuration and Custom Scopes

XML vs Annotation Configuration

Spring supports multiple configuration approaches for defining bean scopes:

XML configuration:

<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="exampleBean" class="com.example.ExampleBean" scope="prototype"/>
    
</beans>

Java configuration:

@Configuration
public class AppConfig {
    
    @Bean
    @Scope("prototype")
    public ExampleBean exampleBean() {
        return new ExampleBean();
    }
}

Custom Scope Implementation

Spring allows developers to register custom scopes by implementing the Scope interface and registering it with the container:

public class ThreadLocalScope implements Scope {
    
    private final ThreadLocal<Map<String, Object>> threadLocal = 
        ThreadLocal.withInitial(HashMap::new);
    
    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        Map<String, Object> scope = threadLocal.get();
        Object object = scope.get(name);
        if (object == null) {
            object = objectFactory.getObject();
            scope.put(name, object);
        }
        return object;
    }
    
    @Override
    public Object remove(String name) {
        Map<String, Object> scope = threadLocal.get();
        return scope.remove(name);
    }
    
    @Override
    public void registerDestructionCallback(String name, Runnable callback) {
        // Implement destruction callback
    }
    
    @Override
    public Object resolveContextualObject(String key) {
        return null;
    }
    
    @Override
    public String getConversationId() {
        return String.valueOf(Thread.currentThread().getId());
    }
}

// Register custom scope
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) applicationContext.getBeanFactory();
beanFactory.registerScope("threadLocal", new ThreadLocalScope());

Conclusion

The Spring bean scope mechanism provides flexible instance management strategies, ranging from global singletons to request-level granular control. Understanding the characteristics and appropriate use cases of each scope enables developers to design more efficient and maintainable Spring applications. In practical development, scope configuration should be selected based on bean state requirements, performance considerations, and thread safety concerns.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.