skip to content

Singleton & Prototype Scopes

Singleton means one instance per container; prototype means a fresh instance per lookup with no destruction callback. The follow-up is always how you inject a prototype into a singleton without freezing one instance at startup.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is the difference between the default singleton scope and prototype scope in Spring?

level: juniorimportance: must knowfreq 85%

answer

  1. singleton = one per container (not per JVM)
  2. prototype = new instance every request/injection
  3. singleton is the default + eager
  4. prototype = no @PreDestroy / destroy callback
  5. prototype cleanup is caller's job

basics

~10 s

A singleton bean is created once per Spring container and shared everywhere. A prototype bean gives a brand-new instance every time it is requested or injected. Singleton is the default.

solid answer

~40 s

By default every Spring bean is a singleton: the container creates exactly one instance per ApplicationContext and hands the same shared object to every injection point and every getBean call. A prototype bean (declared with @Scope("prototype") or @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)) is instantiated fresh on each request — each getBean call and each dependency injection yields a new object. A key consequence: Spring fully manages the singleton lifecycle including destruction callbacks, but for prototypes it creates and wires the bean, then hands it off and forgets it — no @PreDestroy / DisposableBean callback runs at container shutdown. Singleton is the sensible default for stateless services; prototype fits stateful or short-lived objects. Note 'singleton' here means one-per-container, not the GoF one-per-JVM singleton pattern.

code

java · 10 lines
java
@Component                       // no @Scope -> singleton (default)
public class OrderService { }

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ReportBuilder { }   // new instance on every getBean / injection

// Demonstration
ctx.getBean(OrderService.class) == ctx.getBean(OrderService.class);   // true
ctx.getBean(ReportBuilder.class) == ctx.getBean(ReportBuilder.class); // false

go deeper

for a junior

Nail the core contrast: singleton = one shared instance, prototype = new instance each time, singleton is the default.

for a middle

Add that singleton is one-per-container (not per JVM) and that prototypes get no destruction callback.

for a senior

Discuss eager vs lazy creation, statelessness/thread-safety of singletons, and resource-cleanup responsibility for prototypes.

for a principal

Frame scope choice as a design decision around state ownership and lifecycle, and connect to the injection-mismatch problem solved by providers/proxies.

## What a bean scope is A **scope** defines the lifecycle and visibility of a bean instance the Spring container manages — specifically, *how many* instances exist and *how long* they live. Spring has several scopes; the two core, always-available ones (present in any `ApplicationContext`, web or not) are **singleton** and **prototype**. ## Singleton (the default) If you write a `@Component` or `@Bean` with no `@Scope`, it is a **singleton**. The container instantiates it **exactly once per `ApplicationContext`** (per container), caches that single instance, and returns *the same object reference* to: - every `@Autowired` injection point that needs it, - every call to `applicationContext.getBean(...)`. Because the instance is shared across all callers and (typically) across threads, singleton beans should be **stateless** (or use only thread-safe / immutable state). Mutable per-user state on a singleton is a classic concurrency bug. > Important: Spring's "singleton" means **one instance per container**, *not* the Gang-of-Four Singleton pattern (one instance per class loader / JVM enforced by a private constructor). Two different containers each get their own instance. Singletons are **eagerly** created at container startup by default (unless marked `@Lazy`), so wiring errors surface early. ## Prototype Declared with `@Scope("prototype")` (or the constant `ConfigurableBeanFactory.SCOPE_PROTOTYPE`). The container creates a **new instance every single time the bean is requested** — each `getBean` call and each injection point receives a distinct object. Prototypes are always created **lazily**, i.e., only when actually requested, never eagerly at startup. ## The critical lifecycle gotcha: no destruction callback for prototypes For a **singleton**, Spring manages the *full* lifecycle: it calls initialization callbacks (`@PostConstruct`, `InitializingBean.afterPropertiesSet`) **and** destruction callbacks (`@PreDestroy`, `DisposableBean.destroy`, `@Bean(destroyMethod=...)`) when the container shuts down. For a **prototype**, Spring calls initialization callbacks but then **hands the instance to the caller and stops tracking it**. The container does **not** call `@PreDestroy` / `destroy()` on prototypes. Cleanup of resources (closing files, connections, etc.) is the **client's responsibility** — or you can use a custom `BeanPostProcessor` / a configured destroy method invoked manually. This is because the container has no way to know when the caller is done with the object. ## Declaring scope ```java @Component @Scope("prototype") // or @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) class Task { } ``` On a `@Bean` factory method: ```java @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) Task task() { return new Task(); } ``` ## When to use which - **Singleton**: stateless services, DAOs/repositories, controllers, configuration holders — the overwhelming majority of beans. - **Prototype**: objects that hold per-use mutable state, are short-lived, or must not be shared — e.g., a stateful builder, a command object, a per-operation accumulator. ## The classic trap (covered by a sibling question) Injecting a prototype directly into a singleton does **not** give you a new prototype each time you use it — the prototype is resolved **once**, at the moment the singleton is wired, so the singleton keeps the *same* prototype instance forever. Solving that requires `ObjectProvider`, `@Lookup`, `Provider<T>`, or scoped proxies.

  • Does Spring call @PreDestroy on a prototype bean at container shutdown?
    No. Spring manages the full lifecycle of singletons (including destruction callbacks) but only creates and initializes prototypes, then hands them off. Destruction / cleanup of a prototype is the caller's responsibility.
  • Is a Spring singleton the same as the GoF Singleton pattern?
    No. Spring's singleton is one instance per ApplicationContext. The GoF pattern enforces one instance per class loader/JVM via a private constructor. Two Spring containers each hold their own 'singleton' instance.

saying these in an interview costs you the question

  • Saying a Spring singleton means one instance per JVM (it's per container).
  • Claiming @PreDestroy runs on prototype beans at shutdown.
  • Thinking prototype beans are created eagerly at startup like singletons.
  • Assuming a shared singleton is safe to hold per-request mutable state.

context

open as a page

You inject a prototype bean into a singleton with plain @Autowired. Why do you keep getting the same prototype instance, and how do you fix it?

level: middleimportance: must knowfreq 80%

basics

~20 s

Injection happens once, when the singleton is created, so the prototype is resolved a single time and reused forever. To get a fresh instance per use, ask the container each time — via ObjectProvider, @Lookup, JSR-330 Provider, or a scoped proxy.

open as a page

How do you declare a bean as a prototype, and where is @Scope placed on component-scanned vs @Bean-method beans?

level: juniorimportance: should knowfreq 55%

basics

~10 s

Add @Scope("prototype") — or @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE). Put it on the @Component class for scanned beans, or on the @Bean method in a @Configuration class for factory-defined beans.

open as a page

Explain the lifecycle-callback and resource-cleanup differences between singleton and prototype beans, and how you'd reliably clean up a prototype that holds a resource.

level: seniorimportance: should knowfreq 55%

basics

~20 s

For singletons Spring runs both init (@PostConstruct) and destroy (@PreDestroy) callbacks. For prototypes it runs init but never destroy — the container stops tracking them. Clean up prototypes yourself, or via a custom destroy hook you invoke.

open as a page

As an architect, how do you decide between singleton and prototype (and its provider/proxy plumbing), and what are the concurrency, memory, and testing trade-offs at scale?

level: principalimportance: nice to knowfreq 35%

basics

~20 s

Default to stateless singletons — they're cheap, cached, and thread-safe when immutable. Reach for prototype only when you truly need per-use mutable state or non-shareable objects, and inject them via ObjectProvider. Prefer passing state as method parameters over creating stateful beans.

open as a page