Designing Your Own Spring Boot Starter – Part 1

DZone 's Guide to

Designing Your Own Spring Boot Starter – Part 1

Calling all Spring Boot DIYers! Learn how to design a Spring Boot starter, with an intro to the spring.factories file, and @conditional annotations.

· Integration Zone ·
Free Resource

Since its release, Spring Boot has been a huge success: it boosts developers productivity with its convention over configuration philosophy. However, sometimes, it just feels too magical. I have always been an opponent of autowiring for this exact same reason. And when something doesn’t work, it’s hard to get back on track.

This is the reason why I wanted to dig deeper into Spring Boot starter mechanism – to understand every nook and cranny. This post is the first part and will focus on analyzing how it works. The second part will be a case study on creating a starter.


At the root of every Spring Boot starter lies the META-INF/spring.factories file. Let’s check the content of this file in the spring-boot-autoconfigure.jar. Here’s an excerpt of it:

# Auto Configure

Now let’s have a look at their content. For example, here’s the JpaRepositoriesAutoConfiguration class:

@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class,
  JpaRepositoryConfigExtension.class })
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", 
                       name = "enabled", havingValue = "true",
                       matchIfMissing = true)
public class JpaRepositoriesAutoConfiguration {}

There are a couple of interesting things to note:

  1. It’s a standard Spring @Configuration class
  2. The class contains no “real” code but imports another configuration – JpaRepositoriesAutoConfigureRegistrar, which contains the “real” code
  3. There are a couple of @ConditionalOnXXX annotations used
  4. There seems to be an order dependency management of some sort with @AutoConfigureAfter

Points 1 and 2 are self-explanatory, point 4 is rather straightforward so let’s focus on point 3.

@Conditional Annotations

If you didn’t start to work with Spring yesterday, you might know about the @Profile annotation. Profiles are a way to mark a bean-returning method as being optional. When a profile is activated, the relevant profile-annotated method is called and the returning bean contributed to the bean factory.

Some time ago, @Profile looked like that:

public @interface Profile {
    String[] value();

Interestingly enough, @Profile has been rewritten to use the new @Conditional annotation:

@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Profile {
    String[] value();

Basically, a @Conditional annotation just points to a Condition. In turn, a condition is a functional interface with a single method that returns a boolean: if true, the @Conditional-annotated method is executed by Spring and its returning object added to the context as a bean.

There are a lot of conditions available out-of-the-box with Spring Boot:

Condition Description
OnBeanCondition Checks if a bean is in the Spring factory
OnClassCondition Checks if a class is on the classpath
OnExpressionCondition Evalutates a SPeL expression
OnJavaCondition Checks the version of Java
OnJndiCondition Checks if a JNDI branch exists
OnPropertyCondition Checks if a property exists
OnResourceCondition Checks if a resource exists
OnWebApplicationCondition Checks if a WebApplicationContext exists

Those can be combined together with boolean conditions:

Condition Description
AllNestedConditions AND operator
AnyNestedConditions OR operator
NoneNestedCondition NOT operator

Dedicated @Conditional annotations point to those annotations. For example, @ConditionalOnMissingBean points to theOnBeanCondition class.

Time to Experiment

Let’s create a configuration class annotated with @Configuration.

The following method will run in all cases:

public String string() {
    return "string()";

This one won’t, for java.lang.String is part of Java’s API:

public String missingClassString() {
    return "missingClassString()";

And this one will, for the same reason:

public String classString() {
    return "classString()";

Analysis of the previous configuration

Armed with this new knowledge, let’s analyze the above JpaRepositoriesAutoConfiguration class.

This configuration will be enabled if – and only if all conditions are met:

There’s a bean of type  DataSource in the Spring context
The  JpaRepository class is on the classpath  i.e. the project has a dependency on Spring Data JPA
There are no beans of type  JpaRepositoryFactoryBean nor  JpaRepositoryConfigExtension in the context
The standard application.properties file must contain a property named  spring.data.jpa.repositories.enabled with a value of  true

Additionally, the configuration will run after HibernateJpaAutoConfiguration (if the latter is referenced).


I hope I demonstrated that Spring Boot starters are no magic. Join me next week for a simple case study.

To go further:

java, spring, spring boot

Published at DZone with permission of Nicolas Frankel . See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}