Key concepts: @Bean and @Configuration

The central artifacts in Spring's new Java configuration support are classes, marked with the @Configuration annotation, and methods marked with the @Bean annotation.

The @Bean annotation is used to indicate that The method instantiates, configures, and initializes a new object that will be managed by the Spring IoC container. For those familiar with the <beans/> XML configuration from Spring, the @Bean annotation plays the same role as the <bean>. You can use @Bean annotated methods with any @Component annotation from Spring. However, they are most often used with beans annotated with @Configuration.

Annotating a class with @Configuration indicates that its primary purpose is to be a source bean definitions. Moreover, classes annotated with @Configuration allow you to define inter-bean dependencies by calling other @Bean methods in the same class. The simplest possible class, annotated with @Configuration, looks like this:

Java

@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}
Kotlin

@Configuration
class AppConfig {
    @Bean
    fun myService(): MyService {
        return MyServiceImpl()
    }
}

The preceding class AppConfig is equivalent to the following XML class <beans/> from Spring:


 <beans>
     <bean id="myService" class="com.acme.services.MyServiceImpl"/>
 </beans>
Full @Configuration vs. "lite" @Bean mode?

When @Bean methods are declared in classes not annotated with @Configuration, they are called processed in "light" mode. Bean methods declared in the @Component annotation or even in a regular class are considered "lightweight", with the other main purpose of the enclosing class being a method marked with the @Bean annotation. kind of a bonus. For example, utility beans can provide control views to the container through an additional method annotated with @Bean for each class of the corresponding bean. In such scenarios, methods annotated with @Bean are a general-purpose factory method mechanism.

Unlike full @Configuration, wrapped Beanss cannot declare interbean dependencies. Instead, they operate on the internal state of the component that contains them and, optionally, on arguments they may declare. Therefore, such a method marked with the @Bean annotation should not call other methods marked with the @Bean annotation. Each such method is literally just a factory method for a specific bean reference, without any special runtime semantics. A positive side effect here is that there is no need to apply CGLIB subclassification at runtime, so there are no restrictions in terms of class design (so the enclosing class can be final and so on).

In normal scenarios, methods marked with the @Bean annotation should be declared in classes marked with the @Configuration annotation, ensuring that "full" mode and cross-reference redirection are always used to manage the container life cycle. This prevents the same method marked with the @Bean annotation from being accidentally called through a normal Java call, which helps reduce the number of hard-to-find bugs that are difficult to track down when running in "lite" mode.

The @Bean and @Configuration annotations are discussed in detail in the following sections. However, first we will look at the different ways to create a Spring container using Java-based configuration.

Instantiating a Spring container using AnnotationConfigApplicationContext

The following sections describe AnnotationConfigApplicationContext introduced in Spring 3.0. This generic implementation of the ApplicationContext interface can accept as input not only classes annotated with the @Configuration annotation, but also regular classes annotated with the @Component annotation, as well as classes annotated with metadata from JSR-330.

If classes annotated with the @Configuration annotation are specified as input, the class itself annotated with @Configuration , is registered as a bean definition, and all methods declared in the class that are marked with the @Bean annotation are also registered as bean definitions.

If classes are specified that are marked with the @Component, or from JSR-330, they are registered as bean definitions, and dependency injection metadata such as @Autowired or @Inject is assumed to be used in these classes where needed.

Simple design

Just as Spring XML files are used as input when creating a ClassPathXmlApplicationContext, you can use classes , annotated with @Configuration, as input when creating the AnnotationConfigApplicationContext. This allows you to use the entire Spring container without XML, as shown in the following example:

Java

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}
Kotlin

import org.springframework.beans.factory.getBean
fun main() {
    val ctx = AnnotationConfigApplicationContext(AppConfig::class.java)
    val myService = ctx.getBean<MyService>()
    myService.doStuff()
}

As mentioned earlier, AnnotationConfigApplicationContext is not limited to working only with classes annotated with @Configuration. Any @Component or JSR-330 annotated class can be provided as input to the constructor, as shown in the following example:

Java

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}
Kotlin

import org.springframework.beans.factory.getBean
fun main() {
    val ctx = AnnotationConfigApplicationContext(MyServiceImpl::class.java, Dependency1::class.java, Dependency2::class.java)
    val myService = ctx.getBean<MyService>()
    myService.doStuff()
}

The previous example assumes that MyServiceImpl, Dependency1 and Dependency2 use Spring dependency injection annotations such as the @Autowired.

Building a container programmatically using register(Class<?>…​)

You can create AnnotationConfigApplicationContext using a no-argument constructor and then configuring it using the register() method. This approach is especially useful when constructing AnnotationConfigApplicationContext programmatically. The following example shows how to do this:

Java

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.register(AppConfig.class, OtherConfig.class);
    ctx.register(AdditionalConfig.class);
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}
Kotlin

import org.springframework.beans.factory.getBean
fun main() {
    val ctx = AnnotationConfigApplicationContext()
    ctx.register(AppConfig::class.java, OtherConfig::class.java)
    ctx.register(AdditionalConfig::class.java)
    ctx.refresh()
    val myService = ctx.getBean<MyService>()
    myService.doStuff()
}

Enable component scanning using scan(String...)

To enable scanning components, you can annotate your class with @Configuration like this:

Java

@Configuration
@ComponentScan(basePackages = "com.acme") 
public class AppConfig  {
    // ...
}
  1. This annotation allows you to scan components.
Kotlin

@Configuration
@ComponentScan(basePackages = ["com.acme"]) 
class AppConfig  {
    // ...
}
  1. This annotation allows components to be scanned.

Experienced Spring users may be familiar with the Spring equivalent of the XML declaration from the context: namespace, shown in the following example:


<beans>
    <context:component-scan base-package="com.acme"/>
</beans>

In the previous example, the package com.acme is scanned for any classes annotated with @Component, and these classes are registered as Spring bean definitions in the container. AnnotationConfigApplicationContext exposes the scan(String...​) method to provide the same component scanning functionality as shown in the following example:

Java

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.scan("com.acme");
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
}
Kotlin

fun main() {
    val ctx = AnnotationConfigApplicationContext()
    ctx.scan("com.acme")
    ctx.refresh()
    val myService = ctx.getBean<MyService>()
}
Remember that @Configuration classes are meta-annotated with @Component and are therefore candidates for component scanning. In the previous example, assuming AppConfig is declared in the com.acme package (or any other package underneath it), it is intercepted during the scan() . After refresh(), all its methods annotated with @Bean are processed and registered as bean definitions in the container.

Supporting web applications with AnnotationConfigWebApplicationContext

The WebApplicationContext variant of the AnnotationConfigApplicationContext class can be accessed using AnnotationConfigWebApplicationContext. You can use this implementation when setting up a servlet listener ContextLoaderListener from Spring, DispatcherServlet from Spring MVC and so on. The following web.xml snippet configures a typical web application in Spring MVC (note the use of the contextClass context parameters and init parameters):


<web-app>
    <!-- Configuring ContextLoaderListener to use AnnotationConfigWebApplicationContext
        instead of the standard XmlWebApplicationContext -->
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>
    <!-- The configuration location must consist of one or more comma- or space-separated
        fully qualified class names annotated with @Configuration. Full package names can also be -->
    <context-param>
        <param-name>contextConfigLocation>/param-name>
        <param-value>com.acme.AppConfig</param-value>
    </context-param>
    <!-- We bootstrap the root application context as usual, using ContextLoaderListener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-classм
    </listener>
    <!-- Declare the DispatcherServlet in Spring MVC as usual -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Configure the DispatcherServlet to use AnnotationConfigWebApplicationContext
            instead of the standard XmlWebApplicationContext -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>
            <!-- Again, configuration locations must consist of one or more comma- or space-separated
            and fully qualified class names annotated with @Configuration -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.acme.web.MvcConfig</param-value>
        </init-param>
    </servlet>
    <!-- map all requests for /app/* to the dispatcher servlet -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>
For programmatic use cases GenericWebApplicationContext can be used as an alternative to AnnotationConfigWebApplicationContext. For details, see the javadoc at GenericWebApplicationContext.