skip to content

@Configuration & @Bean Factory Methods

@Configuration classes are CGLIB-enhanced so that calling one @Bean method from another returns the cached singleton; lite mode and proxyBeanMethods=false switch that off. A favourite question, because the wrong answer means duplicate beans in production.

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

questions

5

What are @Configuration and @Bean, and how do you use them to define a Spring bean?

level: juniorimportance: must knowfreq 82%

answer

  1. class = recipe book, @Bean = one recipe
  2. bean name defaults to method name
  3. singleton by default, called once
  4. params are autowired dependencies
  5. for third-party classes you can't annotate

basics

~10 s

@Configuration marks a class as a source of bean definitions. Inside it, a method annotated with @Bean returns an object that Spring registers as a bean in the application context, managing its lifecycle.

solid answer

~40 s

@Configuration marks a class as a container-managed source of bean definitions — Java config, the alternative to XML. Each method annotated with @Bean is a factory method: Spring calls it once, takes the returned object, and registers it as a singleton bean in the ApplicationContext. The bean's name defaults to the method name (overridable via @Bean("name")). Method parameters are autowired from other beans, which is how you express dependencies between beans. @Configuration classes are themselves detected by component scanning (they are meta-annotated with @Component) or registered explicitly. This gives you type-safe, refactor-friendly wiring and is the standard way to configure third-party objects you can't annotate with @Component (like a DataSource or RestTemplate).

code

java · 16 lines
java
@Configuration
class AppConfig {

    @Bean
    DataSource dataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:postgresql://localhost/app");
        return ds;
    }

    // method parameter is autowired from the container
    @Bean
    JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

go deeper

for a junior

Know that @Configuration is on the class and @Bean is on a method that returns a managed object; bean name = method name; singleton by default.

for a middle

Explain parameter autowiring for inter-bean dependencies and the @Component vs @Bean decision, plus name/scope overrides.

for a senior

Position Java config against XML and component scanning, mention that @Configuration is a @Component, and note the private/final method restriction hinting at CGLIB.

for a principal

Frame @Bean methods as programmatic BeanDefinition registration and connect to lifecycle, conditionals (@Conditional), and how auto-configuration is built on the same mechanism.

## The problem it solves Spring needs to know which objects to create and manage (its **beans**) and how to wire them together. `@Component` + component scanning works for *your* classes, but you can't put `@Component` on a class you don't own (e.g. `RestTemplate`, a `DataSource`, an SDK client). **Java configuration** solves this: you write plain methods that construct those objects and let Spring manage the results. ## @Configuration `@Configuration` is a class-level annotation (itself meta-annotated with `@Component`, so it's picked up by component scanning). It declares that the class contains **bean definitions**. Think of the class as a recipe book and each `@Bean` method as one recipe. ## @Bean `@Bean` is a method-level annotation. The method is a **factory method**: Spring invokes it, and whatever object it returns becomes a bean in the **ApplicationContext** (Spring's container / registry of managed objects). Key defaults and options: - **Bean name** defaults to the *method name*. Override with `@Bean("myName")` or `@Bean(name = {"a", "b"})` for aliases. - **Scope** defaults to **singleton** — Spring calls the method once and caches the single instance. Add `@Scope("prototype")` for a new instance per lookup. - **Dependencies** are declared as method *parameters*: Spring resolves each parameter by autowiring a matching bean before calling the method. You can also just call another `@Bean` method directly (inter-bean reference) — see full-mode behavior. - **Return type** should be as specific as useful; the declared return type participates in type-based autowiring. ## Minimal example ```java @Configuration class AppConfig { @Bean DataSource dataSource() { var ds = new HikariDataSource(); ds.setJdbcUrl("jdbc:postgresql://localhost/app"); return ds; } @Bean JdbcTemplate jdbcTemplate(DataSource dataSource) { // autowired param return new JdbcTemplate(dataSource); } } ``` Here `jdbcTemplate` depends on `dataSource`; Spring supplies the already-created `DataSource` singleton. ## How it gets loaded - Via component scanning (`@ComponentScan` / Spring Boot auto-config finds `@Configuration` because it's a `@Component`), or - Explicitly: `new AnnotationConfigApplicationContext(AppConfig.class)`, or `@Import(AppConfig.class)`. ## When to use @Bean vs @Component - `@Component`/`@Service`/`@Repository` — for **your own** classes; Spring instantiates them by scanning. - `@Bean` — for **third-party** classes, when construction needs logic/conditionals, or when one method needs to produce several related objects. ## Common gotchas - Forgetting the class-level `@Configuration` (or having only `@Bean` methods in a plain `@Component`) changes semantics ("lite mode" — inter-bean calls create new instances). Covered in the full-vs-lite question. - Two `@Bean` methods with the same method name = duplicate bean names; the second may override or fail depending on `allow-bean-definition-overriding`. - `@Bean` methods must not be `private` or `final` in a full `@Configuration` class (CGLIB needs to override them).

  • What is the default name and scope of a @Bean, and how do you change them?
    Default name is the method name; default scope is singleton. Override the name with @Bean("name"), and the scope with @Scope("prototype") (or another scope) on the same method.
  • When would you use @Bean instead of @Component?
    When the class isn't yours to annotate (third-party types like RestTemplate/DataSource), when construction needs conditional or imperative logic, or when one factory method must produce/assemble several collaborating objects.

saying these in an interview costs you the question

  • Saying @Bean goes on a class (it's method-level; @Configuration is class-level).
  • Claiming the default scope is prototype (it's singleton).
  • Thinking @Bean methods can't take parameters — parameters are the primary way to inject dependencies.
  • Believing you must use XML because a class is third-party — that's exactly what @Bean avoids.

context

open as a page

Explain full mode vs lite mode for @Bean methods. What does CGLIB enhancement of @Configuration classes actually do?

level: middleimportance: must knowfreq 74%

basics

~20 s

In a @Configuration class (full mode), Spring CGLIB-subclasses it so calling one @Bean method from another returns the cached singleton, not a new object. @Bean methods in a plain class (lite mode) aren't intercepted, so each direct call runs the method again.

open as a page

How do initMethod and destroyMethod on @Bean work, and how do they compare to other lifecycle callbacks?

level: middleimportance: should knowfreq 45%

basics

~10 s

@Bean(initMethod="...") names a method Spring calls after the bean is created and dependencies are set; @Bean(destroyMethod="...") names one called on shutdown. They let you run setup/cleanup on third-party classes without annotations.

open as a page

What does @Configuration(proxyBeanMethods = false) do, and when would you set it?

level: seniorimportance: should knowfreq 48%

basics

~20 s

It keeps @Configuration semantics but skips CGLIB enhancement, so the class isn't proxied. @Bean methods then behave like lite mode: direct inter-bean calls create new objects. Use it when methods don't call each other, to speed startup and help native images.

open as a page

What are the practical constraints and costs of CGLIB-based @Configuration enhancement, and how do they influence design in Kotlin and native-image builds?

level: principalimportance: nice to knowfreq 26%

basics

~20 s

Full-mode @Configuration is CGLIB-subclassed, so the class can't be final and @Bean methods can't be private/final. It adds startup cost and needs runtime bytecode, which hurts GraalVM native images. Kotlin needs the all-open plugin; teams often prefer proxyBeanMethods=false with parameter injection.

open as a page