Java > Spring Framework > Spring Boot > Spring Boot Auto-Configuration

Custom Auto-Configuration for Greeting Service

This example demonstrates how to create a custom auto-configuration in Spring Boot. We'll build a simple GreetingService that can be customized through properties. Auto-configuration allows your application to automatically configure beans based on the classpath and properties, reducing boilerplate configuration.

Greeting Service Interface

This interface defines the contract for our greeting service. Different implementations can provide different greetings.

public interface GreetingService {
    String greet(String name);
}

Default Greeting Service Implementation

This is a default implementation of the GreetingService. It uses a greetingMessage property to construct the greeting.

public class DefaultGreetingService implements GreetingService {

    private final String greetingMessage;

    public DefaultGreetingService(String greetingMessage) {
        this.greetingMessage = greetingMessage;
    }

    @Override
    public String greet(String name) {
        return greetingMessage + ", " + name + "!";
    }
}

Greeting Service Properties

This class defines the configuration properties for the greeting service. Spring Boot will automatically bind properties with the prefix 'greeting' to this class.

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("greeting")
public class GreetingServiceProperties {

    private String message = "Hello";

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

Auto-Configuration Class

This is the auto-configuration class. Let's break down the annotations:

  • @Configuration: Indicates that this class provides bean definitions.
  • @ConditionalOnClass(GreetingService.class): Only activates this configuration if the GreetingService class is present on the classpath.
  • @EnableConfigurationProperties(GreetingServiceProperties.class): Enables support for @ConfigurationProperties and binds properties with the prefix 'greeting' to the GreetingServiceProperties class.
  • @ConditionalOnMissingBean: Only creates the greetingService bean if no other bean of type GreetingService is already defined in the application context.
  • @ConditionalOnProperty: Only creates the greetingService bean if the property greeting.enabled is set to true (or if it's not defined, since matchIfMissing = true).

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass(GreetingService.class)
@EnableConfigurationProperties(GreetingServiceProperties.class)
public class GreetingServiceAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "greeting", value = "enabled", havingValue = "true", matchIfMissing = true)
    public GreetingService greetingService(GreetingServiceProperties properties) {
        return new DefaultGreetingService(properties.getMessage());
    }
}

spring.factories File

Create a file named spring.factories in the META-INF directory of your library. This file tells Spring Boot to automatically enable your auto-configuration. The key is org.springframework.boot.autoconfigure.EnableAutoConfiguration, and the value is the fully qualified name of your auto-configuration class.

# Auto-configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\n  com.example.GreetingServiceAutoConfiguration

Using the Greeting Service

In your application, simply inject the GreetingService. The auto-configuration will take care of creating and configuring the bean for you.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class DemoApplication {

    @Autowired
    private GreetingService greetingService;

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

    @Bean
    public CommandLineRunner run() {
        return args -> {
            System.out.println(greetingService.greet("World"));
        };
    }
}

Real-Life Use Case

Auto-configuration is ideal for creating reusable libraries or modules that provide pre-configured functionality. Imagine a database connection pool library; auto-configuration can set up the data source, connection pool settings, and transaction manager based on properties defined in the application's application.properties or application.yml file.

Best Practices

  • Keep auto-configuration classes concise: Focus on configuring the necessary beans and avoid complex logic.
  • Use conditional annotations: Leverage @ConditionalOnClass, @ConditionalOnMissingBean, and @ConditionalOnProperty to control when your auto-configuration takes effect.
  • Provide sensible defaults: Set reasonable default values for configuration properties.
  • Document your auto-configuration: Clearly explain how to use and customize your auto-configuration.

Interview Tip

When discussing auto-configuration in an interview, be prepared to explain the purpose of each annotation (@Configuration, @ConditionalOnClass, @EnableConfigurationProperties, etc.) and how they work together. Also, be able to describe how Spring Boot discovers and activates auto-configurations.

When to Use Them

Use auto-configuration when you want to provide a pre-configured set of beans for a specific functionality and allow users to easily customize it through properties. Avoid auto-configuration if the configuration is highly application-specific and not reusable across different projects.

Alternatives

Alternatives to auto-configuration include manual configuration using @Configuration classes and XML configuration files. However, auto-configuration offers a more convenient and flexible approach for creating reusable components.

Pros

  • Reduced boilerplate: Automates configuration, minimizing the amount of code you need to write.
  • Reusability: Enables you to create reusable libraries and modules.
  • Customization: Allows users to customize the configuration through properties.

Cons

  • Complexity: Can be complex to set up and debug, especially for large and intricate configurations.
  • Potential conflicts: Can lead to conflicts if multiple auto-configurations try to define the same beans. Careful use of conditional annotations can mitigate this.

FAQ

  • What is the purpose of the `spring.factories` file?

    The `spring.factories` file tells Spring Boot where to find the auto-configuration classes to enable. It's a crucial part of the auto-configuration mechanism.
  • How can I disable an auto-configuration?

    You can disable an auto-configuration by using the `spring.autoconfigure.exclude` property in your `application.properties` or `application.yml` file. Specify the fully qualified name of the auto-configuration class to exclude.
  • How do I define properties for my auto-configuration?

    Use the `@ConfigurationProperties` annotation on a class to define the properties. Spring Boot will automatically bind properties with the specified prefix to this class.