Spring Boot Autoconfiguration. How it works underneath
In a Spring Boot Application Overview course, a simple Spring Boot application was created. A lot of topics were covered on a high level, however, details were omitted. In order to be productive in the area of Spring applications development, it is necessary to know what is going on underneath. In some cases, Spring Boot Autoconfiguration has to be disabled for some operations, in others — it should be modified in some way. In this post, we will go through the logic behind Spring Boot Autoconfiguration.
Overview
org.springframework.boot:spring-boot-autoconfigure jar is responsible for autoconfiguration.
It contains:
- AutoConfiguration classes for different tools and situations (e.g. RedisAutoConfiguration for Redis).
- A set of possible properties and their descriptions.
- Common classes to create AutoConfiguration classes, etc.
Configuration Properties
Spring Boot requires configuration properties in order to configure beans in a specific way. They can be specified in various ways. On the one hand, Spring defines default mechanisms to load required properties from specified default locations. On the other hand, a developer can specify the location of the configuration file by themselves.
All possible configuration options can be found in Spring Documentation.
spring-configuration-metadata.json contains details of all supported configuration properties ( metadata details).
{
"groups": [
{
"name": "server",
"type": "org.springframework.boot.autoconfigure.web.ServerProperties",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
{
"name": "server.compression",
"type": "org.springframework.boot.web.server.Compression",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties",
"sourceMethod": "getCompression()"
},
{
"name": "server.error",
"type": "org.springframework.boot.autoconfigure.web.ErrorProperties",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties",
"sourceMethod": "getError()"
}
],
"properties": [
{
"name": "server.address",
"type": "java.net.InetAddress",
"description": "Network address to which the server should bind.",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
{
"name": "server.compression.enabled",
"type": "java.lang.Boolean",
"description": "Whether response compression is enabled.",
"sourceType": "org.springframework.boot.web.server.Compression",
"defaultValue": false
}
],
"hints": [
{
"name": "server.servlet.jsp.class-name",
"providers": [
{
"name": "class-reference",
"parameters": {
"target": "javax.servlet.http.HttpServlet"
}
}
]
},
{
"name": "server.tomcat.accesslog.encoding",
"providers": [
{
"name": "handle-as",
"parameters": {
"target": "java.nio.charset.Charset"
}
}
]
}
]
}
- properties specify specific values that are used for configuration.
- groups represent high-level objects that contain properties.
- hints are used to specify additional information about properties.
additional- spring-configuration-metadata.json is used to specify additional custom information about properties. E.g.
{
"properties": [
{
"name": "server.compression.mime-types",
"description": "Comma-separated list of MIME types that should be compressed.",
"defaultValue": [
"text/html",
"text/xml",
"text/plain",
"text/css",
"text/javascript",
"application/javascript",
"application/json",
"application/xml"
]
}
]
}
It is done because initial spring-configuration-metadata.json is generated and some changes can be required from the application perspective ( Metadata details).
Spring Boot Autoconfigurations
Spring Boot Autoconfigurations are specified at spring.factories. Some of them are:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
All possible autoconfiguration classes are located in org.springframework.boot.autoconfigure package.
In order to eagerly filter out configurations that are not active spring-autoconfigure-metadata.properties is used. E.g.
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration=
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration.AutoConfigureAfter=org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
org.springframework.boot.autoconfigure.amqp.RabbitAnnotationDrivenConfiguration=
org.springframework.boot.autoconfigure.amqp.RabbitAnnotationDrivenConfiguration.ConditionalOnClass=org.springframework.amqp.rabbit.annotation.EnableRabbit
Conditions
Spring Boot provides a bunch of handful conditional annotations at org.springframework.boot.autoconfigure.condition package. E.g.
- @ConditionalOnBean
- @ConditionalOnClass
- @ConditionalOnCloudPlatform
- @ConditionalOnExpression
- @ConditionalOnJava
- @ConditionalOnJndi
- @ConditionalOnMissingBean
- @ConditionalOnMissingClass
- @ConditionalOnNotWebApplication
- @ConditionalOnProperty
- @ConditionalOnResource
- @ConditionalOnSingleCandidate
- @ConditionalOnWarDeployment
- @ConditionalOnWebApplication
Custom conditions can also be created.
Let’s look at HibernateJpaAutoConfiguration:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class, SessionImplementor.class })
@EnableConfigurationProperties(JpaProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
@Import(HibernateJpaConfiguration.class)
public class HibernateJpaAutoConfiguration {
}
Firstly, it is specified that Hibernate has to be autoconfigured after DataSourceAutoConfiguration.
Secondly, @ConditionalOnClass specifies that in order to activate this configuration LocalContainerEntityManagerFactoryBean.class, EntityManager.class, and SessionImplementor.class have to be in the classpath. It is achieved by adding specific starter dependency into the Gradle or Maven configuration file.
If starter is enabled, HibernateJpaConfiguration is used to configure a bunch of beans.
Other auto configurations have a similar logic mostly based on class/bean existence/non-existence. The same logic can be created for custom autoconfiguration. It is worth mentioning that Spring Boot Autoconfiguration is performed after your custom beans are created.
Spring Boot Autoconfiguration Report
Spring Boot can show you an autoconfiguration report on application start-up. To do it, the next property has to be specified in the application properties file:
The report will look similar to the next lines:
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
AopAutoConfiguration matched:
- @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)
AopAutoConfiguration.ClassProxyingConfiguration matched:
- @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)
- @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)
Summary
In this post, Spring Boot Autoconfiguration was reviewed. It is important to know the logic underneath because in some cases configuration has to be changed, disabled, or even created from scratch. Having the knowledge of autoconfiguration makes it possible to use the full power of Spring.
In order to check all this classes, just create a Spring Boot Application without dependencies in Spring Initializr.
Originally published at https://datamify.com on June 11, 2021.