Spring @Configuration Annotation with Example

In this article, we will discuss a very important Spring Java based configuration annotation that is a @Configuration annotation with examples.

Spring @Configuration annotation is part of the spring core framework. Spring Configuration annotation indicates that the class has @Bean definition methods. So Spring container can process the class and generate Spring Beans to be used in the application.

@Configuration Annotation Overview

@Configuration is a class-level annotation indicating that an object is a source of bean definitions. @Configuration classes declare beans via public @Bean annotated methods. Calls to @Bean methods on @Configuration classes can also be used to define inter-bean dependencies.
Spring Boot favors Java-based configuration. Although it is possible to use SpringApplication with XML sources, Spring Boot community generally recommend that our primary source be a single @Configuration class. Usually, the class that defines the main method is a good candidate as the primary @Configuration.
Tip: Many Spring configuration examples have been published on the Internet that uses XML configuration. If possible, always try to use the equivalent Java-based configuration. Searching for Enable* annotations can be a good starting point.

Importing Additional Configuration Classes 

You need not put all your @Configuration into a single class. The @Import annotation can be used to import additional configuration classes. Alternatively, you can use @ComponentScan to automatically pick up all Spring components, including @Configuration classes.
Read more about @Import annotation on Spring @Import Annotation with Example

Importing XML Configuration

If you have used XML based configuration, then you can use an @ImportResource annotation to load XML configuration files.

Read more about @ImportResource annotation on Spring @PropertySource Annotation with Example

Refer below diagram shows an internal implementation for your reference.
The simplest possible @Configuration class would read as follows:
import org.springframework.boot.SpringApplication;
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 AppConfig class above would be equivalent to the following Spring XML:
<beans>
        <bean id="customerService" class="com.companyname.projectname.CustomerService"/>
        <bean id="orderService" class="com.companyname.projectname.OrderService"/>
</beans>

Injecting inter-bean dependencies

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();
    }
}
In the example above, the foo bean receives a reference to bar via constructor injection.

How Java-based configuration works internally?

The following example shows a @Bean annotated method being called twice:
@Configuration
public class AppConfig {

    @Bean
    public ClientService clientService1() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientService clientService2() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientDao clientDao() {
        return new ClientDaoImpl();
    }
}
clientDao() has been called once in clientService1() and once in clientService2(). Since this method creates a new instance of ClientDaoImpl and returns it, you would normally expect to have 2 instances (one for each service). That definitely would be problematic: in Spring, instantiated beans have a singleton scope by default. This is where the magic comes in: All @Configuration classes are subclassed at startup-time with CGLIB. 
In the subclass, the child method checks the container first for any cached (scoped) beans before it calls the parent method and creates a new instance. Note that as of Spring 3.2, it is no longer necessary to add CGLIB to your classpath because CGLIB classes have been repackaged under org.springframework.cglib and included directly within the spring-core JAR. The behavior could be different according to the scope of your bean. We are talking about singletons here.

Constraints when authoring @Configuration classes

  • Configuration classes must be provided as classes (i.e. not as instances returned from factory methods), allowing for runtime enhancements through a generated subclass.
  • Configuration classes must be non-final.
  • Configuration classes must be non-local (i.e. may not be declared within a method).
  • Any nested configuration classes must be declared as static.
  • @Bean methods may not, in turn, create further configuration classes (any such instances will be treated as regular beans, with their configuration annotations remaining undetected).


Comments