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.

@Configuration
public class AppConfig {

    @Bean
    public TransferServiceImpl transferService() {
        return new TransferServiceImpl();
    }
}

The above Java configuration is equivalent to the following XML:

<beans>
    <bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

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:

@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

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:

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();
    }
}

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.

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();
    }
}

Bean Scopes

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

@Configuration
public class MyConfiguration {

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

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.

// 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;
}

Custom Bean Naming

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

@Configuration
public class AppConfig {

    @Bean("myThing")
    public Thing thing() {
        return new Thing();
    }
}

Bean Aliases

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

@Configuration
public class AppConfig {

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

Bean Description

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

@Configuration
public class AppConfig {

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

End of guide.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

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

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.