@Configuration spring boot

In this article, we will learn the meaning and use of @Configuration annotation in a spring boot application with examples.

@Configuration annotation
This annotation is applied over a class in spring boot to indicate that this class contains bean definitions.
In other words, it contains methods that return spring beans. These methods are annotated with @Bean annotation.

When a spring boot application starts, all the methods annotated with @Bean annotation written inside the class annotated with @Configuration are executed to create bean instances.

As per spring docs for @Configuration,

Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.

Bean instances created have the default scope as singleton. This means that you will get same instance of a bean every time.
@Configuration annotation example
Below is a class that has @Configuration annotation and a single @Bean method.

@Configuration
public class ConfigurationDemo {

  @Bean
  public BeanA getBeanA() {
    return new BeanA();
  }
}

Below is the class definition for BeanA

public class BeanA {
 
  public BeanA() {
    System.out.println("*** Creating instance ***");
  }
}

Now, as soon as spring boot application is started, the container looks for @Configuration classes and invokes all its @Bean methods.

Below are the logs printed on the console

2021-08-23 23:27:47.594 INFO 24880 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-08-23 23:27:47.603 INFO 24880 — [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-08-23 23:27:47.603 INFO 24880 — [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.52]
2021-08-23 23:27:47.669 INFO 24880 — [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-08-23 23:27:47.669 INFO 24880 — [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 710 ms
*** Creating instance ***

@Configuration with @Autowired
Spring container creates beans for the methods defined in @Configuration class. These beans can be injected in other classes with @Autowired annotation.
So, you can easily inject an instance of BeanA in any spring managed class with @Autowired as shown below.

@Component 
public class DataManager {

  @Autowired
  BeanA beanA;

  // other code

}

Lazy loading beans
All @Bean methods defined in @Configuration class are executed as the spring container starts. This means that @Bean  methods have eager initialization.
However, this behavior can be controlled with @Lazy annotation so that beans are initialized only when required. Example,

@Configuration
@Lazy
public class ConfigurationDemo { 

  @Bean
  public BeanA beanA() {
    return new BeanA();
  }
}

@Bean method will not be called on application startup. It will be called when BeanA needs to be initialized.

@Lazy can also be used over individual @Bean methods as shown below

@Configuration 
public class ConfigurationDemo { 

  @Bean 
  public BeanA beanA() { 
    return new BeanA(); 
  } 

  @Bean
  @Lazy 
  public BeanC beanC() {
    return new BeanC();
  }
}

In this case, BeanA will be eagerly initialized while BeanC will be lazily initialized on demand.

@Configuration with @Profile
Similar to @Lazy, beans can be loaded on the basis of active profiles using @Profile annotation in conjunction with @Configuration.
@Profile can be applied at the class level so that all @Bean methods will be invoked if a particular profile is active as shown below.

@Configuration 
@Profile("prod") 
public class ConfigurationDemo { 

  @Bean 
  public DataSource getDataSource() { 
    return new DataSource(); 
  } 
}

In this case, getDataSource() will be invoked only when active profile is “prod”.

@Profile can be applied at individual @Bean methods so that they are invoked according to the active profile. Example,

@Configuration 
public class ConfigurationDemo { 

  @Bean 
  @Profile("prod")
  public DataSource getProdDataSource() { 
    return new ProdDataSource(); 
  } 

  @Bean 
  @Profile("staging")
  public DataSource getStagedDataSource() { 
    return new StagedDataSource(); 
  } 
}

In above example, @Bean method corresponding to the active profile will be invoked.

Needless to say, you can combine @Configuration, @Lazy and @Profile annotations to load beans as they are required(lazily), according to the active profile.
Removing @Configuration
If you remove @Configuration annotation and try to autowire a bean defined in this class, you will get

Field beanA in com.codippa.DataManager required a bean of type ‘com.codippa.BeanA’ that could not be found.

This shows that @Bean methods defined inside @Configuration classes are automatically invoked by spring container.

Though there is no reason to remove @Configuration from a class. But, if you still need to remove it, you can get bean instances defined in this class using AnnotationConfigApplicationContext as below

AnnotationConfigApplicationContext ct = new AnnotationConfigApplicationContext();
// register configuration class manually
ct.register(ConfigurationDemo.class);
ct.refresh();
// get bean instance
BeanA beanA = ct.getBean(BeanA.class);
ct.close();

Notice that here we are manually registering our configuration class, which is otherwise, done automatically with @Configuration.

Thus, @Configuration annotation in spring boot is used to initialize beans. All @Bean methods defined in this class are automatically invoked at container startup unless marked as lazy.
Hope the article was useful.