The central artifacts in Spring’s Java configuration support are
@Configuration
-annotated classes and @Bean
-annotated methods.
The @Bean
annotation is used to indicate that a method instantiates, configures, and
initializes a new object to be managed by the Spring IoC container. For those familiar
with Spring’s <beans/>
XML configuration, the @Bean
annotation plays the same role as
the <bean/>
element. You can use @Bean
-annotated methods with any Spring
@Component
. However, they are most often used with @Configuration
beans.
Annotating a class with @Configuration
indicates that its primary purpose is as a
source of bean definitions. Furthermore, @Configuration
classes let inter-bean
dependencies be defined by calling other @Bean
methods in the same class.
The simplest possible @Configuration
class reads as follows:
- Java
-
@Configuration public class AppConfig { @Bean public MyServiceImpl myService() { return new MyServiceImpl(); } }
- Kotlin
-
@Configuration class AppConfig { @Bean fun myService(): MyServiceImpl { return MyServiceImpl() } }
The preceding AppConfig
class is equivalent to the following Spring <beans/>
XML:
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
In common scenarios, @Bean
methods are to be declared within @Configuration
classes,
ensuring that full configuration class processing applies and that cross-method
references therefore get redirected to the container’s lifecycle management.
This prevents the same @Bean
method from accidentally being invoked through a regular
Java method call, which helps to reduce subtle bugs that can be hard to track down.
When @Bean
methods are declared within classes that are not annotated with
@Configuration
- or when @Configuration(proxyBeanMethods=false)
is declared -,
they are referred to as being processed in a "lite" mode. In such scenarios,
@Bean
methods are effectively a general-purpose factory method mechanism without
special runtime processing (that is, without generating a CGLIB subclass for it).
A custom Java call to such a method will not get intercepted by the container and
therefore behaves just like a regular method call, creating a new instance every time
rather than reusing an existing singleton (or scoped) instance for the given bean.
As a consequence, @Bean
methods on classes without runtime proxying are not meant to
declare inter-bean dependencies at all. Instead, they are expected to operate on their
containing component’s fields and, optionally, on arguments that a factory method may
declare in order to receive autowired collaborators. Such a @Bean
method therefore
never needs to invoke other @Bean
methods; every such call can be expressed through
a factory method argument instead. The positive side-effect here is that no CGLIB
subclassing has to be applied at runtime, reducing the overhead and the footprint.
The @Bean
and @Configuration
annotations are discussed in depth in the following sections.
First, however, we cover the various ways of creating a Spring container by using
Java-based configuration.