Spring - Bean Scopes

Spring allows you to control how many instances of a bean are created and for how long they live. The scope of a bean defines its lifecycle and visibility within the ApplicationContext. The six built-in scopes are: singleton, prototype, request, session, application and websocket.

Contents

Singleton scope (default)

The singleton scope is the default. Spring creates exactly one instance per ApplicationContext and every request for that bean returns the same shared instance. Ideal for stateless beans.

Java
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

// Singleton is the default — no @Scope annotation needed.
@Service
public class CacheService {

    private final Map<String, Object> cache = new ConcurrentHashMap<>();

    public void put(String key, Object value) { cache.put(key, value); }
    public Object get(String key) { return cache.get(key); }
}
Java
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
CacheService a = ctx.getBean(CacheService.class);
CacheService b = ctx.getBean(CacheService.class);
System.out.println(a == b); // true — same instance

Prototype scope

With prototype scope Spring creates a new instance each time the bean is requested. Use this for stateful beans. Note: Spring does not call destroy callbacks on prototype beans.

Java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;

@Component
@Scope("prototype")
public class ShoppingCart {

    private final List<CartItem> items = new ArrayList<>();

    public void addItem(CartItem item) { items.add(item); }
    public List<CartItem> getItems() { return items; }
}
Java
ShoppingCart cart1 = ctx.getBean(ShoppingCart.class);
ShoppingCart cart2 = ctx.getBean(ShoppingCart.class);
System.out.println(cart1 == cart2); // false — different instances

Request scope (web-aware)

The request scope creates a new bean for each HTTP request. The bean lives for the duration of the request and is discarded afterwards. Only available in a web-aware ApplicationContext.

Java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;

@Component
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class RequestContext {

    private String traceId;

    public String getTraceId() { return traceId; }
    public void setTraceId(String traceId) { this.traceId = traceId; }
}

Session scope (web-aware)

The session scope creates a new bean per HTTP session. The same instance is shared across all requests within the same user session. Useful for per-user data such as authentication details.

Java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import java.io.Serializable;

@Component
@Scope(WebApplicationContext.SCOPE_SESSION)
public class UserSessionData implements Serializable {

    private String loggedInUser;
    private String preferredLanguage = "en";

    public String getLoggedInUser() { return loggedInUser; }
    public void setLoggedInUser(String user) { this.loggedInUser = user; }
    public String getPreferredLanguage() { return preferredLanguage; }
    public void setPreferredLanguage(String lang) { this.preferredLanguage = lang; }
}

Note: Session-scoped beans must be Serializable if the HTTP session is persisted or replicated across nodes.