Configuration or AutoConfiguration?

Janani Subbiah
Javarevisited
Published in
4 min readMar 30, 2021

--

Understanding the difference between Configurations and AutoConfigurations in Spring boot!

Photo by Greg Rakozy on Unsplash

Spring boot is all about magic. You add dependencies to the classpath and stuff just fits together and works. It provides a canvas for you to build on. The out-of-the-box configurations are opinionated and will make default configuration choices, at the same time these opinions and the configurations will be the first ones to get out of your way if you want to make your own configuration choices.

A lot of this magic because of AutoConfigurations. AutoConfiguration classes are very very similar to regular Configuration classes except for the following two differences:

  • AutoConfiguration classes are run last (meaning after all regular non-autoconfiguration classes) while the order in which Configuration classes are run is indeterminate (except if we use ordering annotations like @Ordered)
  • To declare a class as an AutoConfiguration they need to be specified as such in the spring.factories file. An example can be found here.

By now I am sure you are wondering when should one choose an AutoConfiguration class vs a Configuration class. Great question! Personally, I like to use an AutoConfiguration when:

  • The creation of beans depends on the presence of other beans. In other words, if you are considering using the @ConditionalOnBean or the @ConditionalOnMissingBean annotations.
  • Your configuration depends on other AutoConfigurations. You can use the @AutoConfigureAfter or @AutoConfigureBefore annotations to control the order of beans creation when it comes to AutoConfiguration classes.

Let's look at some examples (and do some logging to understand the sequence of beans creation):

Beans using only @Configuration

Let's make some very very basic and simple examples. Consider two utility classes: StringUtils and ObjectUtils :

class StringUtils {    fun isBlank(value: String): Boolean {      // Implementation here    }    // Other utility methods will go here}class ObjectUtils {    fun isNull(value: Object?): Boolean {      // Implementation here    }    // Other utility methods will go here}

Next, we are going to be creating a StringUtilsConfiguration class:

@Configuration
class StringUtilsConfiguration {
@Bean
fun stringUtils(): StringUtils {
logger.info("Running StringUtilsConfiguration")
return StringUtils()
}
companion object { private val logger = Logger.getLogger(this.javaClass.name)
}
}

and an ObjectUtilsConfiguration class:

@Configuration
class ObjectUtilsConfiguration {
@Bean
fun objectUtils(): ObjectUtils {
logger.info("Running ObjectUtilsConfiguration")
ObjectUtils()
}
companion object { private val logger = Logger.getLogger(this.javaClass.name)
}
}

If we were to run this spring boot application you should see the following log statements:

Running ObjectUtilsConfiguration
Running StringUtilsConfiguration

In order to control the order of execution we could use the @Order annotation. But this is easy when there are only configuration classes. Ordering becomes hard if we had many configuration classes or if we need to conditionally create or not create beans depending on if other beans are present. Finally, if we want to provide defaults (E.g.: to provide defaults)- Enter AutoConfigurations.

Introducing AutoConfigurations

AutoConfiguration classes, as mentioned earlier, are a big component of what makes Spring Boot so effective. We can find several AutoConfiguration classes in Spring boot’s source code. Some example include: FlywayAutoConfiguration, GsonAutoConfiguration, MailSenderAutoConfiguration etc.

On a lot of these classes you may see some form of an @Conditionalxxx annotation. So these classes are executed when those conditions are fullfilled.

Let us start off with creating an AutoConfiguration and for simplicity’s sake let us change the StringUtilsConfiguration class to be an AutoConfiguration. The only thing we will need to do is register the StringUtilsConfiguration as an AutoConfiguration by creating a spring.factories file under the src/main/resource/META-INF directory:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfiguration.sample.ObjectUtilsConfiguration

Now if we were to run the app, we will see that the ObjectUtilsConfiguration class will be run last, always.

This truly shines when a configuration class or even just the creation of a bean depends on the presence or the absence of some other bean. The @ConditionalOnBean would be an annotation to use, BUT from the documentation of the annotation:

@Conditional that only matches when beans meeting all the specified requirements are already contained in the BeanFactory. All the requirements must be met for the condition to match, but they do not have to be met by the same bean.

As mentioned the @ConditionalOnBean only looks at the current state of the BeanFactory and not if the bean will ever be present in the application. So if the class that creates a certain bean that your configuration depends on another configuration, one option is to make your configuration an AutoConfiguration to make sure it is run after all other non-autoconfiguration classes. If your configuration depends on another AutoConfiguration, using one of @AutoConfigureAfter or @AutoConfigureBefore would help.

Conclusion

It is very VERY easy to create our own magic code similar to Spring boot to have things work “automagically”. But there eventually comes a point where it becomes extremely important to know and understand the difference between the options available to make that magic work. One such good-to-understand topic as far as Spring boot goes is AutoConfigurations for sure! And I hope my blog post, at the very least, scratched the surface :)

--

--

Janani Subbiah
Javarevisited

Product Architect | Ice cream lover | Newbie gardener