Backend Development 9 min read

Mastering Spring @Bean: Declaration, Dependencies, Lifecycle & Scopes

This guide explains how to use Spring's @Bean annotation to declare beans, configure dependencies, control lifecycle callbacks, set custom scopes, assign names, aliases, and descriptions, providing Java code examples that parallel equivalent XML configurations.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Spring @Bean: Declaration, Dependencies, Lifecycle & Scopes

Environment

Spring version 5.3.25.

@Bean Annotation Basics

@Bean is a method‑level annotation that directly corresponds to the XML <bean/> element. It supports attributes such as init-method , destroy-method , autowiring , and name . You can place @Bean on methods inside @Configuration or @Component classes.

Declaring a Bean

Annotate a method with @Bean to register a bean definition in the ApplicationContext; the bean type is the method's return type and the default bean name matches the method name.

<code>@Configuration
public class AppConfig {

    @Bean
    public TransferServiceImpl transferService() {
        return new TransferServiceImpl();
    }
}
</code>

The above Java configuration is equivalent to the following XML:

<code>&lt;beans&gt;
    &lt;bean id="transferService" class="com.acme.TransferServiceImpl"/&gt;
&lt;/beans&gt;
</code>

Both configurations make a bean named transferService of type TransferServiceImpl available in the ApplicationContext.

Bean Dependencies

A @Bean method can declare parameters that the container will resolve as dependencies. For example, if TransferService needs an AccountRepository :

<code>@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}
</code>

Bean Lifecycle

Beans defined with @Bean support standard lifecycle callbacks, including JSR‑250 annotations @PostConstruct and @PreDestroy . They also honor Spring’s own callbacks if the bean implements InitializingBean , DisposableBean , or Lifecycle , and they can use any of the *Aware interfaces.

You can specify custom init and destroy methods just like the XML init-method and destroy-method attributes:

<code>public class BeanOne {
    public void init() {
        // initialization logic
    }
}

public class BeanTwo {
    public void cleanup() {
        // destruction logic
    }
}

@Configuration
public class AppConfig {

    @Bean(initMethod = "init")
    public BeanOne beanOne() {
        return new BeanOne();
    }

    @Bean(destroyMethod = "cleanup")
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}
</code>

If a bean has public close or shutdown methods, Spring will invoke them by default. To disable this behavior, set destroyMethod="" on the @Bean definition.

<code>public class Main {
    static class Person {
        public void close() { System.out.println("close"); }
        public void shutdown() { System.out.println("shutdown"); }
    }
    @Configuration
    static class AppConfig {
        // @Bean(destroyMethod = "") disables automatic close/shutdown
        @Bean
        public Person person() { return new Person(); }
    }
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
            new AnnotationConfigApplicationContext(AppConfig.class);
        context.close();
    }
}
</code>

Bean Scopes

Use the @Scope annotation to change a bean’s scope. The default is singleton , but you can specify others such as prototype :

<code>@Configuration
public class MyConfiguration {

    @Bean
    @Scope("prototype")
    public Encryptor encryptor() {
        // ...
    }
}
</code>

Spring also supports scoped proxies via the proxyMode attribute of @Scope, allowing beans with narrower scopes (e.g., session) to be injected into singleton beans.

<code>// an HTTP Session‑scoped bean exposed as a proxy
@Bean
@SessionScope
public UserPreferences userPreferences() {
    return new UserPreferences();
}

@Bean
public Service userService() {
    UserService service = new SimpleUserService();
    // reference to the proxied userPreferences bean
    service.setUserPreferences(userPreferences());
    return service;
}
</code>

Custom Bean Naming

By default the method name becomes the bean name, but you can override it with the name attribute:

<code>@Configuration
public class AppConfig {

    @Bean("myThing")
    public Thing thing() {
        return new Thing();
    }
}
</code>

Bean Aliases

Provide multiple names for a single bean using the name attribute with a string array:

<code>@Configuration
public class AppConfig {

    @Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
    public DataSource dataSource() {
        // instantiate, configure and return DataSource bean...
    }
}
</code>

Bean Description

Attach a textual description to a bean with @Description, useful for monitoring tools such as JMX:

<code>@Configuration
public class AppConfig {

    @Bean
    @Description("Provides a basic example of a bean")
    public Thing thing() {
        return new Thing();
    }
}
</code>

End of guide.

JavaconfigurationSpringLifecycledependency injectionBeanScope
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.