BackendBench
Coffee

Unravel › Java concepts › Spring and Boot

Spring

@Configuration, @Bean and bean wiring

A @Configuration class is a recipe for creating beans in plain Java.

Learn these first

At a glance

Mental model

A seating plan for a wedding: the guests (classes) exist already, and the plan decides who sits at which table (which bean goes where).

What happens, in order
  1. 1A method annotated @Bean inside a @Configuration class returns an object; Spring registers it under the method nameThis is how you wire third-party classes you cannot annotate yourself (a RestTemplate, a DataSource).
  2. 2When two beans share a type, injection is ambiguous@Primary marks the default; @Qualifier("name") at the injection point picks one explicitly.
  3. 3@Scope("prototype") creates a new instance for every injection (the default singleton shares one)@Scope("request") ties a bean to one web request.
  4. 4@Lazy delays creation until first use; @DependsOn forces an order; @Import pulls in other configuration classes; @Order sorts lists of beans of the same type
Remember
Watch out
Injecting a prototype into a singleton and expecting new instancesTwo beans of one type without @Primary or @QualifierCalling a @Bean method from a @Component and getting a second instanceCircular dependencies hidden by @Lazy instead of fixed
Example (highlighted lines explain it)
@Configurationpublic class PaymentConfig {    @Bean    @Primary    public PaymentGateway stripeGateway(StripeProperties props) {        return new StripeGateway(props.apiKey());    }    @Bean    @Qualifier("fallback")    public PaymentGateway offlineGateway() {        return new OfflineGateway();    }}
  1. line 4 uses Primary, the core of @Configuration, @Bean and bean wiring
  2. line 10 uses Qualifier, the core of @Configuration, @Bean and bean wiring
Read the full explanation (about 2 min)

A @Configuration class is a recipe for creating beans in plain Java. This is where you control which implementation is injected, how many instances exist, and when they are created.

A mental model

A seating plan for a wedding: the guests (classes) exist already, and the plan decides who sits at which table (which bean goes where). @Primary is the guest of honour who gets the seat unless someone else is named.

How it works

A method annotated @Bean inside a @Configuration class returns an object; Spring registers it under the method name. This is how you wire third-party classes you cannot annotate yourself (a RestTemplate, a DataSource).

When two beans share a type, injection is ambiguous. @Primary marks the default; @Qualifier("name") at the injection point picks one explicitly.

@Scope("prototype") creates a new instance for every injection (the default singleton shares one). @Scope("request") ties a bean to one web request.

@Lazy delays creation until first use; @DependsOn forces an order; @Import pulls in other configuration classes; @Order sorts lists of beans of the same type.

Going deeper

Inside a @Configuration class, calling one @Bean method from another returns the same singleton, because the class is subclassed by CGLIB. In a plain @Component, the same call would create a second object.

Injecting a prototype bean into a singleton gives you one instance for the singleton lifetime. To get a fresh one each time use ObjectProvider<T> and call getObject().

Conditional beans (@Profile, @ConditionalOnProperty) let one codebase run differently in tests, on a laptop and in production without if-statements.

Under the hood

The container reads each @Bean method as a bean definition with a factory method. ConfigurationClassPostProcessor runs before ordinary beans are created, parses the configuration classes and registers their definitions, which is why configuration classes themselves cannot depend on beans they define.

Common mistakes

  • Injecting a prototype into a singleton and expecting new instances.
  • Two beans of one type without @Primary or @Qualifier.
  • Calling a @Bean method from a @Component and getting a second instance.
  • Circular dependencies hidden by @Lazy instead of fixed.

How Unravel recognises it

When you paste code, Unravel looks for these signs of @configuration, @bean and bean wiring. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Frequently asked questions

What is @Configuration, @Bean and bean wiring?

A @Configuration class is a recipe for creating beans in plain Java. This is where you control which implementation is injected, how many instances exist, and when they are created.

What are the most common mistakes with @Configuration, @Bean and bean wiring?

Injecting a prototype into a singleton and expecting new instances. Two beans of one type without @Primary or @Qualifier. Calling a @Bean method from a @Component and getting a second instance. Circular dependencies hidden by @Lazy instead of fixed.

How can I see @Configuration, @Bean and bean wiring in real code?

Paste your own Java into Unravel and it will point out where @configuration, @bean and bean wiring appears, explain how it works at the detail level you choose, and draw the flow of the code around it.