Over a million developers have joined DZone.

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

Build APIs from SQL and NoSQL or Salesforce data sources in seconds. Read the Creating REST APIs white paper, brought to you in partnership with CA Technologies.

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:

OnBeanConditionChecks if a bean is in the Spring factory
OnClassConditionChecks if a class is on the classpath
OnExpressionConditionEvalutates a SPeL expression
OnJavaConditionChecks the version of Java
OnJndiConditionChecks if a JNDI branch exists
OnPropertyConditionChecks if a property exists
OnResourceConditionChecks if a resource exists
OnWebApplicationConditionChecks if a WebApplicationContext exists

Those can be combined together with boolean conditions:

AllNestedConditionsAND operator
AnyNestedConditionsOR operator
NoneNestedConditionNOT 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:

The Integration Zone is brought to you in partnership with CA Technologies.  Use CA Live API Creator to quickly create complete application backends, with secure APIs and robust application logic, in an easy to use interface.

spring,java,spring boot

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

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}