If you work in a company that develops shared libraries, or if you work on an open-source or commercial library, you might want to develop your own auto-configuration. Auto-configuration classes can be bundled in external jars and still be picked-up by Spring Boot.
Auto-configuration can be associated to a "starter" that provides the auto-configuration code as well as the typical libraries that you would use with it. We first cover what you need to know to build your own auto-configuration and then we move on to the typical steps required to create a custom starter.
Tip | |
---|---|
A demo project is available to showcase how you can create a starter step-by-step. |
Under the hood, auto-configuration is implemented with standard @Configuration
classes.
Additional @Conditional
annotations are used to constrain when the auto-configuration
should apply. Usually, auto-configuration classes use @ConditionalOnClass
and
@ConditionalOnMissingBean
annotations. This ensures that auto-configuration applies
only when relevant classes are found and when you have not declared your own
@Configuration
.
You can browse the source code of spring-boot-autoconfigure
to see the @Configuration
classes that we provide (see the
META-INF/spring.factories
file).
Spring Boot checks for the presence of a META-INF/spring.factories
file within your
published jar. The file should list your configuration classes under the
EnableAutoConfiguration
key, as shown in the following example:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\ com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
You can use the
@AutoConfigureAfter
or
@AutoConfigureBefore
annotations if your configuration needs to be applied in a specific order. For example,
if you provide web-specific configuration, your class may need to be applied after
WebMvcAutoConfiguration
.
If you want to order certain auto-configurations that should not have any direct
knowledge of each other, you can also use @AutoConfigureOrder
. That annotation has the
same semantic as the regular @Order
annotation but provides a dedicated order for
auto-configuration classes.
Note | |
---|---|
Auto-configurations must be loaded that way only. Make sure that they are defined in a specific package space and that, in particular, they are never the target of component scanning. |
You almost always want to include one or more @Conditional
annotations on your
auto-configuration class. The @ConditionalOnMissingBean
annotation is one common
example that is used to allow developers to ‘override’ auto-configuration if they are
not happy with your defaults.
Spring Boot includes a number of @Conditional
annotations that you can reuse in your
own code by annotating @Configuration
classes or individual @Bean
methods. These
annotations include:
The @ConditionalOnClass
and @ConditionalOnMissingClass
annotations let
configuration be included based on the presence or absence of specific classes. Due to
the fact that annotation metadata is parsed by using ASM, you can
use the value
attribute to refer to the real class, even though that class might not
actually appear on the running application classpath. You can also use the name
attribute if you prefer to specify the class name by using a String
value.
Tip | |
---|---|
If you use |
The @ConditionalOnBean
and @ConditionalOnMissingBean
annotations let a bean be
included based on the presence or absence of specific beans. You can use the value
attribute to specify beans by type or name
to specify beans by name. The search
attribute lets you limit the ApplicationContext
hierarchy that should be considered
when searching for beans.
When placed on a @Bean
method, the target type defaults to the return type of the
method, as shown in the following example:
@Configuration public class MyAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService() { ... } }
In the preceding example, the myService
bean is going to be created if no bean of type
MyService
is already contained in the ApplicationContext
.
Tip | |
---|---|
You need to be very careful about the order that bean definitions are added as these
conditions are evaluated based on what has been processed so far. For this reason, we
recommend only using |
Note | |
---|---|
|
The @ConditionalOnProperty
annotation lets configuration be included based on a Spring
Environment property. Use the prefix
and name
attributes to specify the property that
should be checked. By default, any property that exists and is not equal to false
is
matched. You can also create more advanced checks by using the havingValue
and
matchIfMissing
attributes.
The @ConditionalOnResource
annotation lets configuration be included only when a
specific resource is present. Resources can be specified by using the usual Spring
conventions, as shown in the following example: file:/home/user/test.dat
.
The @ConditionalOnWebApplication
and @ConditionalOnNotWebApplication
annotations
let configuration be included depending on whether the application is a 'web
application'. A web application is any application that is using a Spring
WebApplicationContext
, defines a session
scope, or has a StandardServletEnvironment
.
The @ConditionalOnExpression
annotation lets configuration be included based on the
result of a SpEL expression.
A full Spring Boot starter for a library may contain the following components:
autoconfigure
module that contains the auto-configuration code.starter
module that provides a dependency to the autoconfigure
module as well
as the library and any additional dependencies that are typically useful. In a nutshell,
adding the starter should provide everything needed to start using that library.Tip | |
---|---|
You may combine the auto-configuration code and the dependency management in a single module if you do not need to separate those two concerns. |
You should make sure to provide a proper namespace for your starter. Do not start your
module names with spring-boot
, even if you are using a different Maven groupId
. We
may offer an official support for the thing you auto-configure in the future.
As a rule of thumb, you should name a combined module after the starter. For example,
assume that you are creating a starter for "acme" and that you name the auto-configure
module acme-spring-boot-autoconfigure
and the starter acme-spring-boot-starter
. If
you only have one module that combines the two, name it acme-spring-boot-starter
.
Also, if your starter provides configuration keys, use a proper (that is, unique)
namespace for them. In particular, do not include your keys in the namespaces that Spring
Boot uses (such as server
, management
, spring
, and so on). If you use the same
namespace, we may modify these namespaces in the future in ways that break your modules.
Make sure to
trigger
meta-data generation so that IDE assistance is available for your keys as well. You may
want to review the generated meta-data (META-INF/spring-configuration-metadata.json
) to
make sure your keys are properly documented.
The autoconfigure
module contains everything that is necessary to get started with the
library. It may also contain configuration key definitions (such as
@ConfigurationProperties
) and any callback interface that can be used to further
customize how the components are initialized.
Tip | |
---|---|
You should mark the dependencies to the library as optional so that you can include
the |
The starter is really an empty jar. Its only purpose is to provide the necessary dependencies to work with the library. You can think of it as an opinionated view of what is required to get started.
Do not make assumptions about the project in which your starter is added. If the library you are auto-configuring typically requires other starters, mention them as well. Providing a proper set of default dependencies may be hard if the number of optional dependencies is high, as you should avoid including dependencies that are unnecessary for a typical usage of the library. In other words, you should not include optional dependencies.