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

Conditional Bean Creation with Auto-Configuration

This example demonstrates how to use conditional annotations to control when a bean is created in an auto-configuration. We'll create a simple message sender bean that is only created if a specific property is set to true.

Message Sender Interface

This interface defines the contract for sending messages.

public interface MessageSender {
    void sendMessage(String message);
}

Message Sender Implementation

This is a simple implementation of the MessageSender that logs the message.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultMessageSender implements MessageSender {

    private static final Logger logger = LoggerFactory.getLogger(DefaultMessageSender.class);

    @Override
    public void sendMessage(String message) {
        logger.info("Sending message: {}", message);
    }
}

Message Sender Auto-Configuration

This is the auto-configuration class. The @ConditionalOnProperty annotation ensures that the messageSender bean is only created if the property message.sender.enabled is set to true in the application properties or environment variables.

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MessageSenderAutoConfiguration {

    @Bean
    @ConditionalOnProperty(prefix = "message.sender", name = "enabled", havingValue = "true")
    public MessageSender messageSender() {
        return new DefaultMessageSender();
    }
}

spring.factories File

Add the auto-configuration class to the spring.factories file to enable it.

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

Application Usage

In your application, inject the MessageSender. Note the use of required = false in the @Autowired annotation. This is because the bean may not be created if the property is not set. Check if the bean is null before using it.

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(required = false)
    private MessageSender messageSender;

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

    @Bean
    public CommandLineRunner run() {
        return args -> {
            if (messageSender != null) {
                messageSender.sendMessage("Hello, World!");
            } else {
                System.out.println("MessageSender is not enabled.");
            }
        };
    }
}

Setting the Property

To enable the message sender, set the message.sender.enabled property to true in your application.properties or application.yml file.

# application.properties
message.sender.enabled=true

Concepts Behind the Snippet

The core concept revolves around Conditional Bean Creation using @ConditionalOnProperty. This allows developers to selectively instantiate beans based on the presence and value of configuration properties, making the application highly configurable and adaptable to different environments or deployments.

Real-Life Use Case

Consider a feature flag system. You might have a NewFeatureService that you only want to enable for a subset of users or during a beta testing phase. Using @ConditionalOnProperty, you can control whether this service is available based on a property like new.feature.enabled=true, allowing you to easily toggle the feature on or off without redeploying the application.

Best Practices

  • Use descriptive property names: Make the property names clear and self-explanatory (e.g., message.sender.enabled instead of just enabled).
  • Provide a default value: Consider the matchIfMissing attribute of @ConditionalOnProperty to determine the behavior when the property is not set.
  • Document your properties: Clearly document the purpose of each property and its possible values.

Interview Tip

Be prepared to discuss the various conditional annotations available in Spring Boot (@ConditionalOnClass, @ConditionalOnBean, @ConditionalOnMissingBean, @ConditionalOnWebApplication, etc.) and how they can be used to create flexible and configurable applications.

When to Use Them

Use conditional bean creation when you need to control the creation of beans based on external factors, such as environment variables, system properties, or the presence of other beans. This is particularly useful for creating optional features or services.

Alternatives

Alternatives include using profiles or manually creating beans based on conditional logic in your configuration classes. However, conditional annotations provide a more declarative and maintainable approach.

Pros

  • Flexibility: Allows you to easily enable or disable features based on configuration.
  • Maintainability: Makes your configuration more declarative and easier to understand.
  • Testability: Simplifies testing by allowing you to easily control the creation of beans in your tests.

Cons

  • Increased complexity: Can make your configuration more complex if overused.
  • Potential for confusion: Can be difficult to understand the dependencies between beans if the conditional logic is not clear.

FAQ

  • What happens if the property is not defined?

    By default, if the property is not defined, the condition is not matched. However, you can use the `matchIfMissing` attribute to change this behavior. Setting `matchIfMissing = true` will cause the condition to be matched if the property is not defined.
  • Can I use multiple conditional annotations on a single bean?

    Yes, you can use multiple conditional annotations on a single bean. All conditions must be met for the bean to be created.
  • How can I test conditional bean creation?

    You can use Spring's testing framework to set properties and verify that the beans are created or not created as expected. You can override properties in your test configuration.