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 is a method-level annotation and a direct analog of the XML element <bean />. The annotation supports some of the attributes offered by, such as init-method, destroy-method, autowiring and name.
  • You can use the @Bean annotation in a @Configuration-annotated or in a @Component-annotated class.
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>
Note that the method name and bean name in XML are exactly same.
Let's look at different scenarios in which @Bean annotation is used.

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

The @Bean annotation supports specifying arbitrary initialization and destruction callback methods, much like Spring XML’s init-method and destroy-method attributes on the bean element:
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, configuration classes use a @Bean method’s name as the name of the resulting bean. This functionality can be overridden, however, with the name attribute.
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.

Comments