skip to content

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%

answer

  1. @Scope on the class (scanned) or on the @Bean method
  2. use SCOPE_PROTOTYPE constant, not raw string
  3. no @Scope = singleton (default)
  4. proxyMode = TARGET_CLASS / INTERFACES for scoped proxy
  5. @RequestScope/@SessionScope exist; no @PrototypeScope

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.

solid answer

~40 s

You mark a bean prototype with the @Scope annotation. For a component-scanned bean, place @Scope on the class alongside @Component/@Service/etc. For a bean defined by a factory method, place @Scope on the @Bean method inside the @Configuration class. Prefer the constant ConfigurableBeanFactory.SCOPE_PROTOTYPE over the raw string "prototype" to avoid typos. Omitting @Scope means singleton — you rarely write @Scope("singleton") explicitly since it's the default. @Scope also drives web scopes ("request", "session", "application", "websocket") and supports a proxyMode attribute (ScopedProxyMode.TARGET_CLASS / INTERFACES) used to inject shorter-lived scoped beans into longer-lived ones. The scope name is what a custom Scope implementation registers under, so the mechanism is extensible.

code

java · 12 lines
java
// Component-scanned
@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PaymentAttempt { }

// Factory method with a scoped proxy so a singleton can hold it
@Configuration
class Cfg {
    @Bean
    @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
    PaymentAttempt paymentAttempt() { return new PaymentAttempt(); }
}

go deeper

for a junior

Know the annotation and where it goes (class vs @Bean method) and that omission = singleton.

for a middle

Mention the constants and the proxyMode attribute existence.

for a senior

Explain proxyMode's role and the composed @RequestScope/@SessionScope meta-annotations.

for a principal

Discuss the pluggable Scope SPI: scope names are keys registered via CustomScopeConfigurer, making scope an extension point.

## The @Scope annotation `org.springframework.context.annotation.@Scope` sets a bean's scope. Its `value` (aliased as `scopeName`) is the scope name string. The two core names are `"singleton"` and `"prototype"`; web-aware contexts add `"request"`, `"session"`, `"application"`, `"websocket"`. Because raw strings are typo-prone, Spring exposes constants: - `ConfigurableBeanFactory.SCOPE_SINGLETON` = `"singleton"` - `ConfigurableBeanFactory.SCOPE_PROTOTYPE` = `"prototype"` - `WebApplicationContext.SCOPE_REQUEST` / `SCOPE_SESSION` / `SCOPE_APPLICATION` for web scopes. ## Placement **Component-scanned bean** — annotate the class: ```java @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class ReportBuilder { } ``` **@Bean factory method** — annotate the method in a `@Configuration` class: ```java @Configuration public class AppConfig { @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public ReportBuilder reportBuilder() { return new ReportBuilder(); } } ``` Putting `@Scope` anywhere else (e.g., on an injection point) has no effect on the bean definition. ## Singleton is implicit Omitting `@Scope` yields singleton. Writing `@Scope("singleton")` is legal but redundant; you almost never see it. ## The proxyMode attribute `@Scope` has a `proxyMode` attribute of type `ScopedProxyMode`: - `NO` (default), - `TARGET_CLASS` (CGLIB subclass proxy), - `INTERFACES` (JDK dynamic proxy), - `DEFAULT`. A scoped proxy lets you inject a shorter-lived bean (prototype/request/session) into a longer-lived singleton: the singleton actually holds a proxy that resolves the real target *per call*. This is one of several ways to fix the prototype-in-singleton mismatch (covered in a dedicated question). ## Meta-annotation shortcuts Spring ships composed annotations so you don't write `@Scope` by hand for web scopes: `@RequestScope`, `@SessionScope`, `@ApplicationScope` (each is `@Scope(...)` with `proxyMode = TARGET_CLASS` baked in). There is no `@PrototypeScope` meta-annotation — you write `@Scope(SCOPE_PROTOTYPE)` explicitly. ## XML equivalent (legacy) In XML it's `<bean id="..." class="..." scope="prototype"/>`. The annotation form is the modern default.

  • Why prefer ConfigurableBeanFactory.SCOPE_PROTOTYPE over the string "prototype"?
    The constant is compile-time checked, so a typo becomes a build error rather than a silent fallback/failure at runtime. It also documents intent and survives IDE refactors.

saying these in an interview costs you the question

  • Thinking @Scope on an injection point changes the bean's scope.
  • Believing there is a @PrototypeScope meta-annotation.
  • Claiming you must write @Scope("singleton") to get a singleton.

context