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