Expanding on Property Injection with Spring Boot Auto-Configuration

In a previous post, we discovered how auto-configuration in Spring Boot enables bean and configuration creation.

In Spring, managing settings, configuring beans, or handling application constants, properly injecting properties into the environment is crucial. Here we’ll explore different methods of injecting properties in a Spring Boot auto-configuration setup.

Programmatic Property Injection

One method for injecting properties is programmatically adding them to the ConfigurableEnvironment.

@Configuration
public class ConfigInjection {
    @Autowire ConfigurableEnvironment environment;
    
    @PostConstruct
    public void performAction() {
        environment.getPropertySources().addFirst(new PropertiesPropertySource("propKey", "propValue"));
    }
    
}

Using @PropertySource with application.properties

Another simple case is using application.properties or application.yml files in combination with the @PropertySource annotation.

@PropertySource(value = "classpath:foo.properties")


However, here we have some limitations, when using @PropertySource. For example, Spring Boot loads certain properties, like logging.* and spring.main.*, before the application context is refreshed. This means these properties cannot be configured through @PropertySource because they are needed too early in the lifecycle.

You can read more about this in the Spring Boot external configuration documentation.

such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.

When Does the Context Get Refreshed?

The context is refreshed during the initialization phase of a Spring application, but before the application starts running.
Specifically, this happens after the beans are instantiated but before certain critical configurations—like logging properties (logging.*) or Spring Boot’s core settings (spring.main.*)—are applied.

These particular properties need to be set early because they control foundational behaviors like logging, classpath scanning, and profile management, which need to be established before the application context is fully created and refreshed.
So properties required early need to be set before the context refresh process, typically through external configuration files like application.properties or environment variables, or programatically, not by @PropertySource.

Injecting Properties for Bean Creation

If you want to inject properties into beans at the time of their creation, you can use the @Value annotation:

@Component
public class MyBean {
	@Value("${property.injectable.at.bean.creation.time}")
	private String name;
	// ...
}

Setting up properties before App Context Creation

Defining properties before the application context is created, you can implement an ApplicationContextInitializer in your auto-conf library:

In the META-INF/spring.factories file or META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports, you would register your initializer:

org.springframework.context.ApplicationContextInitalizer=\
com.example.config.MyPropConfiguration

Sample implementation:

public class MyPropConfiguration implements ApplicationContextInitalizer<ConfigurableApplicationContext>{
    @Override
    public void initalize(ConfigurableApplicationContext appContext){
        appContext.getEnvironment().getPropertySources().addFirst(
            new PropertiesPropertySource("propKey", "propValue")
        )
    }
} 

Conclusion

We wnt through on multiple approaches to injecting properties in a Spring Boot application, with their advantages and disadvantages. depending on the specific needs. Understanding these different methods enables you to make better decisions choosing configurations across different environments and stages of your application lifecycle.

Programmatic injection allows flexible configuration at runtime, where properties need to be defined or modified on the fly.
On the other hand, using @PropertySource simplifies configuration by loading properties from external files, with the limitations when dealing with early-loaded settings, such as logging and core Spring Boot properties.

In case where properties needed before the appContext is fully initialized, implementing an ApplicationContextInitializer can help, ensuring that configurations are loaded early.

Ultimately, the choosing right method to manage configs can significantly improve the maintainability or in complex cases the scalability, and flexibility of your application.

One thought on “Expanding on Property Injection with Spring Boot Auto-Configuration”

Leave a Reply

Your email address will not be published. Required fields are marked *