Debunking The Magic behind Spring Boot

Author: Shazin Sadakath


"One man's 'magic' is another man's engineering" - Robert A. Heinlein

Spring boot is a very famous rapid application development platform which enables default auto configurations based on whats available in the classpath and enables to write applications which just run. Fuelled by the expansion of Microservices based architecture, Spring boot has caught up as a very developer friendly platform.

But for the uninitiated this may look like magic as they have no clue how a Spring boot application actually run. This post is one of many to come which are intended educate readers on this.

Let's look at a typical Spring boot application like following:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

It has a crucial code which does the so called magic. It is the @SpringBootApplication. This is actually a combination of three annotations. @SpringBootConfiguration, @ComponentScan, @EnableAutoConfiguration. In this @ComponentScan is responsible to load all the beans defined by the developer of the application in user configuration. And @EnableAutoConfiguration is responsible to all the beans defined the auto configuration by Spring or third party libraries.

Writing a custom Spring Boot Auto Configuration

A basic auto configuration will have a spring.factories file under META-INF directory with the following content:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.github.shazin.greeter.starter.config.GreeterServiceAutoConfiguration

This entry will mark a particular @Configuration file as an Auto configuration for a module. Similar to @DataSourceAutoConfiguration which will create a DataSource for a Database application.

But how to find out whether the application has database, message queue or anything similar which needs Auto configuration? This can be solved using many of the @Conditional... annotations available in the Spring boot starter. The GreeterServiceAutoConfiguration in our case using @ConditionalOnClass and @ConfitionalOnMissingBean.

import com.github.shazin.greeter.service.GreeterService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass(GreeterService.class)
public class GreeterServiceAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public GreeterService greeterService() {
        return new GreeterService("Welcome", "Mr");
    }

}

Where the Auto configuration will only kick if GreeterService class is available in the classpath and greeterService bean instance will only be created if there is no bean defined of that type.

Using the custom Spring Boot Auto Configuration

So in order to use the bean defined by the auto configuration, just need to have the jar containing the spring.factories and auto configuration in the classpath.

import com.github.shazin.greeter.service.GreeterService;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class GreetingApplication {

    public static void main(String... args) {
        SpringApplication.run(GreetingApplication.class, args);
    }

    @Bean
    public ApplicationRunner applicationRunner(GreeterService greeterService) {
        return args -> {
            System.out.println(greeterService.greet("Shazin"));
        };
    }

//    Uncomment to Override GreeterServiceAutoconfiguration greeterService
//    @Bean
//    public GreeterService greeterService() {
//        return new GreeterService("Greeting", "Dr");
//    }
}

Now the ApplicationRunner can use the auto configured GreeterService and if the auto configured one needs to be overridden then can define a custom bean and auto configuration will safely fallback. 

Complete source is available in Github



Tags: SpringBoot AutoConfiguration Inner Working
Views: 329
Register for more exciting articles

Comments

Please login or register to post a comment.


There are currently no comments.