1. Introduction
In this tutorial, we’ll discuss @Bean
annotation which is a very important annotation to know.
A Java object instance managed by Spring container is called bean. This annotation is typically used to define methods to create beans.
You can use the @Bean
annotation in a @Configuration
-annotated or in a @Component
-annotated class. A method annotated with @Bean registers a bean definition within an ApplicationContext
of the type specified as the method’s return value.
Following is the declaration of @Bean
annotation:
@Target(value={METHOD,ANNOTATION_TYPE}) @Retention(value=RUNTIME) @Documented public @interface Bean
@Bean
is a method-level annotation and a direct analog of the XML <bean/>
element. This annotation is used on a method and indicates that the method produces a bean to be managed by the Spring container. Following is a typical example of using @Bean annotation:
@Bean public MyBean myBean() { // instantiate and configure MyBean obj return obj; }
@Bean annotation does not provide attributes for profile, scope, lazy, depends-on or primary. If you need these then @Scope
, @Lazy
, @DependsOn
and @Primary
annotations are available separately. For example:
@Bean @Profile("production") @Scope("prototype") public MyBean myBean() { // instantiate and configure MyBean obj return obj; }
The annotation supports some of the attributes offered by <bean/>
, such as:
- init-method
- destroy-method
- autowiring
- name
2. Bean names
By default the name of the bean is the name of the method. However, the @Bean
annotation provides a name()
attribute. The name()
attribute can be used to provide name and alias explicitly for the bean. The name()
attribute accepts an array of Strings, i.e. a primary bean name plus one or more aliases for a single bean.
@Bean({"name1", "alias1"}) // Both 'name1' and 'alias1' are valid names for bean public MyBean myBean() { // instantiate and configure MyBean obj return obj; }
3. @Bean Methods in @Configuration Classes
Typically, @Bean
methods are declared within @Configuration
classes. One @Bean
method can call another @Bean
method. These method calls are called as ‘inter-bean references‘.
@Configuration public class AppConfig { @Bean public MyService myService() { return new MyService(myRepository()); } @Bean public MyRepository myRepository() { return new JdbcMyRepository(dataSource()); } // ... }
4. @Bean with default methods
You can use default methods to define beans. This allows composition of bean configurations by implementing interfaces with bean definitions on default methods.
public interface BaseConfig { @Bean default MyServiceImpl myService() { return new MyServiceImpl(); } } @Configuration public class AppConfig implements BaseConfig { }
5. @Bean Lite Mode
Typically, @Bean
methods are declared in @Configuration
classes. However, it is not mandatory. Bean methods may be declared even in a plain old class or a class not declared with @Configuration
such as @Component
. In such cases, a @Bean
method will get processed in a so-called ‘lite‘ mode. Bean methods in lite mode will be treated as plain factory methods by the container (similar to factory-method declarations in XML), with scoping and lifecycle callbacks properly applied. The ‘inter-bean references’ are not supported in lite mode.
6. Bean Dependencies
A method annotated with @Bean can accept any number of parameters, each representing a dependency needed to create that bean.
For instance, if our MyService
requires an SomeDependencyRepository
, we can materialize that dependency with a method parameter, as the following example shows:
@Configuration public class AppConfig { @Bean public MyService myService(SomeDependencyRepository someDependencyRepository) { return new MyServiceImpl(someDependencyRepository); } }
The resolution mechanism is pretty much identical to constructor-based dependency injection.
7. BeanFactoryPostProcessor-returning @Bean methods
@Bean
method which return BeanFactoryPostProcessor
types should be declared as static
. This is because these methods should be instantiated very early in the container lifecycle else these can create lifecycle issues. By marking this method as static
, such methods can be invoked without causing instantiation of its declaring @Configuration
class, thus avoiding the above-mentioned lifecycle conflicts.
8. Lifecycle Callbacks
Any classes defined with the @Bean
annotation support the regular lifecycle callbacks and can use the @PostConstruct
and @PreDestroy
annotations from JSR-250.
The standard Spring lifecycle callbacks are also fully supported. If a bean implements InitializingBean
, DisposableBean
, or Lifecycle
, the container will invoke their corresponding methods.
The standard set of *Aware
interfaces (such as BeanFactoryAware, BeanNameAware, ApplicationContextAware, MessageSourceAware and so on) are also fully supported.
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(); } }
9. @Scope with @Bean
You can specify that your beans defined with the @Bean
annotation should have a specific scope.
@Configuration public class MyConfiguration { @Bean @Scope("prototype") public MyService myService() { // ... } }
10. Bean Description
To add a description to a @Bean
, you can use the @Description
annotation. Here is an example:
@Configuration public class AppConfig { @Bean @Description("Provides a basic example of a bean") public MyService myService() { return new MyService(); } }
11. Conclusion
In conclusion, the @Bean
annotation in Spring is a powerful tool for defining and managing beans within a Spring application context. By using this annotation, developers can specify the beans that should be managed by the Spring container, along with their dependencies, lifecycle callbacks, and other configurations. Understanding how to effectively utilize the @Bean
annotation allows for more flexible and maintainable code, leveraging Spring’s comprehensive dependency injection capabilities to build robust and scalable applications.