Spring @Bean Annotation with Example

In this article, we will discuss Spring Java configuration-based @Bean annotation with examples. We will also discuss different scenarios of how and when to use @Bean annotation.

@Bean Annotation Overview

@Bean annotation indicates that a method produces a bean to be managed by the Spring container. The @Bean annotation is usually declared in the Configuration class to create Spring Bean definitions.

The below diagram shows an internal implementation of @Bean Annotation:

Declaring a Bean and Example

To declare a bean, simply annotate a method with the @Bean annotation. You use this method to register a bean definition within an ApplicationContext of the type specified as the method’s return value.

By default, the bean name will be the same as the method name.

The following is a simple example of a @Bean method declaration:

import org.springframework.context.annotation.Bean;
                import org.springframework.context.annotation.Configuration;
                
                import com.companyname.projectname.customer.CustomerService;
                import com.companyname.projectname.order.OrderService;
                
                @Configuration
                public class Application {
                
                    @Bean
                    public CustomerService customerService() {
                        return new CustomerService();
                    }
                 
                    @Bean
                    public OrderService orderService() {
                       return new OrderService();
                    }
                }

The preceding configuration is exactly equivalent to the following Spring XML:

<beans>
                <bean id="customerService" class="com.companyname.projectname.CustomerService"/>
                <bean id="orderService" class="com.companyname.projectname.OrderService"/>
        </beans>

Injecting Bean Dependencies

A @Bean annotated method can have an arbitrary number of parameters describing the dependencies required to build that bean. For instance, if our CustomerController requires a CustomerService we can materialize that dependency via a method parameter:

import org.springframework.context.annotation.Bean;
                import org.springframework.context.annotation.Configuration;
                
                import com.companyname.projectname.customer.CustomerController;
                import com.companyname.projectname.customer.CustomerService;
                
                @Configuration
                public class Application {
                
                    private CustomerService customerService;  
                    @Bean
                    public CustomerService customerService() {
                        customerService = new CustomerService();
                        return customerService;
                    }
                 
                    @Bean
                    public CustomerController customerController(CustomerService customerService) {
                        return new CustomerController(customerService);
                    }
                }

The resolution mechanism is pretty much identical to constructor-based dependency injection.

Bean life cycle methods

@Bean annotation provides initMethod and destroyMethod attributes to perform certain actions after bean initialization or before bean destruction by a container.

public class Foo {
                public void init() {
                        // initialization logic via xml config
                }
        }
        
        public class Bar {
                public void cleanup() {
                        // destruction logic via xml config
                }
        }
        
        @Configuration
        public class AppConfig {
        
                @Bean(initMethod = "init")
                public Foo foo() {
                        return new Foo();
                }
        
                @Bean(destroyMethod = "cleanup")
                public Bar bar() {
                        return new Bar();
                }
        
        }

Specifying Bean Scope Using the @Scope Annotation

You can specify that your beans defined with the @Bean annotation should have a specific scope. You can use any of the standard scopes specified in the Bean Scopes. The default scope is a singleton, but you can override this with the @Scope annotation:

import org.springframework.context.annotation.Bean;
                import org.springframework.context.annotation.Configuration;
                import org.springframework.context.annotation.Scope;
                
                import com.companyname.projectname.customer.CustomerService;
                import com.companyname.projectname.order.OrderService;
                
                @Configuration
                public class Application {
                
                    @Bean
                    @Scope("prototype")
                    public CustomerService customerService() {
                        return new CustomerService();
                    }
                 
                    @Bean
                    @Scope("prototype")
                    public OrderService orderService() {
                        return new OrderService();
                    }
                }

Customizing Bean Naming

By default, the bean name is the same as the method name. We can specify the bean name using the name attribute of @Bean annotation:

import org.springframework.context.annotation.Bean;
                import org.springframework.context.annotation.Configuration;
                
                import com.companyname.projectname.customer.CustomerService;
                import com.companyname.projectname.order.OrderService;
                
                @Configuration
                public class Application {
                
                    @Bean(name = "cService")
                    public CustomerService customerService() {
                        return new CustomerService();
                    }
                 
                    @Bean(name = "oService")
                    public OrderService orderService() {
                        return new OrderService();
                    }
                }

Bean Aliasing

As discussed in Naming beans, it is sometimes desirable to give a single bean multiple names, otherwise known as bean aliasing. The name attribute of the @Bean annotation accepts a String array for this purpose.

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

Injecting inter-bean dependencies

When @Bean have dependencies on one another, expressing that dependency is as simple as having one bean method call another:

@Configuration
                    public class AppConfig {
                            @Bean
                            public Foo foo() {
                                    return new Foo(bar());
                            }
                    
                            @Bean
                            public Bar bar() {
                                    return new Bar();
                            }
                    }

That's all about @Bean annotation.