Spring Bean Scopes: Singleton, Prototype, and Web-Aware Lifecycles

The Spring Framework manages object lifecycles through five distinct bean scopes. These determine how many instances are created, how long they persist, and under what conditions they are destroyed.

Singleton

This is the default scope. The container creates exactly one shared instance of the bean for the entire ApplicationContext. It is typically instantiated during container startup unless configured for lazy initialization. This instance remains in memory until the context itself shuts down.

Prototype

A new bean object is generated every time the container resolves a dependency or when code explicitly calls getBean(). Unlike singletons, prototype-scoped objects are not created when the context initializes; they are manufactured on demand. The Spring container does not track the complete lifecycle of these instances after handoff.

Request

A bean definition with request scope produces a new instance for every incoming HTTP request. The object lives from the moment the request is accepted until the response is fully processed. This scope is only valid within a WebApplicationContext.

Session

This scope binds a single bean instance to an HTTP session. It is created upon the first request within a new session and remains available for every subsequent request from the same client until the session is invalidated or times out. Like request scope, this requires a WebApplicationContext.

Global Session

Global session scope associates a bean with a global HTTP session, primarily in Portlet-based applications where multiple portlets share one unified session. It is also restricted to a WebApplicationContext.

Comparing Scope Durations

The visibility and longevity of these scopes increase as follows:

prototype < request < session < global session < singleton

Why Scopes Matter

Defining an appropriate scope isolates state and prevents race conditions. By constraining a bean to the narrowest necessary lifecycle, you avoid unnecessary memory overhead and insure that concurrent threads or user sessions do not unintentionally share mutable data.

Request Scope in Practice

XML configuration:

<bean id="requestCounter" class="com.app.RequestCounter" scope="request"/>

Java configuration:

@RestController
@RequestScope
public class RequestCounter {
    private int hits = 0;

    @GetMapping("/count")
    public int tally() {
        return hits++;
    }
}

For every HTTP request, the container instantiates a separate RequestCounter. Modifications made to the hits field during the request are invisible to other requests because each thread operates on its own distinct object. Once the response is committed, the bean is eligible for garbage collection.

Session Scope in Practice

XML configuration:

<bean id="sessionTracker" class="com.app.SessionTracker" scope="session"/>

Java configuration:

@RestController
@SessionScope
public class SessionTracker {
    private int views = 0;

    @GetMapping("/view")
    public int recordView() {
        return views++;
    }
}

During an HTTP session’s lifetime, the container supplies the same SessionTracker instance for every request associated with that session. State changes—such as incrementing views—accumulate across requests but remain isolated from other sessions. When the underlying HTTP session is invalidated by the container or the JVM, the scoped bean is destroyed alongside it.

Tags: Spring Framework Bean Scopes Spring MVC Dependency Injection java

Posted on Wed, 24 Jun 2026 17:20:17 +0000 by jitesh