Backend Development 8 min read

Mastering Custom Spring Boot Starters: Version Differences & Real‑World AOP Example

This article explains what custom Spring Boot starters are, why they are useful, outlines the annotation and configuration file changes across Spring Boot 2.6, 2.7 and 3.x, and provides a complete AOP‑based starter implementation with code samples.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Custom Spring Boot Starters: Version Differences & Real‑World AOP Example

1. Introduction

Custom starters are a Spring Boot extension mechanism that lets developers package related dependencies, configuration, and auto‑configuration classes into a reusable module. By adding the starter as a Maven or Gradle dependency, Spring Boot automatically scans and loads its configuration, providing one‑stop service for the required technologies.

Why create a custom starter? It enables reuse of common modules (e.g., security, logging, validation) across projects, simplifies dependency management, reduces configuration errors, and improves maintainability.

2. Differences Between Spring Boot Versions

2.1 Annotation changes

Before 2.7, auto‑configuration classes are marked with @Configuration . Starting with 2.7, the new @AutoConfiguration meta‑annotation is used, which itself is annotated with @Configuration to keep the class a standard configuration class.

<code>@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore
@AutoConfigureAfter
public @interface AutoConfiguration {
  @AliasFor(annotation = Configuration.class)
  String value() default "";
  @AliasFor(annotation = AutoConfigureBefore.class, attribute = "value")
  Class<?>[] before() default {};
  @AliasFor(annotation = AutoConfigureBefore.class, attribute = "name")
  String[] beforeName() default {};
  @AliasFor(annotation = AutoConfigureAfter.class, attribute = "value")
  Class<?>[] after() default {};
  @AliasFor(annotation = AutoConfigureAfter.class, attribute = "name")
  String[] afterName() default {};
}</code>

2.2 Configuration file locations

Before 2.7, Spring Boot looks for META-INF/spring.factories where EnableAutoConfiguration keys list the configuration classes.

<code>org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pack.aop.autoconfigure.PackAspectAutoConfiguration,\
xxx,\
yyy,\
zzz</code>

From 2.7 onward, the file META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports is used, listing one class per line.

<code>com.pack.aop.autoconfigure.PackAspectAutoConfiguration
xxx
yyy
zzz</code>

In Spring Boot 3.x only the AutoConfiguration.imports file is consulted.

2.3 Controlling auto‑configuration order

Pre‑2.7 you use @AutoConfigureBefore or @AutoConfigureAfter on a @Configuration class.

<code>@Configuration
@AutoConfigureBefore({DataSourceAutoConfiguration.class})
public class PackAspectAutoConfiguration {}
</code>

From 2.7 you can set the order directly on @AutoConfiguration via its before and after attributes.

<code>@AutoConfiguration(before = {DataSourceAutoConfiguration.class})
public class PackAspectAutoConfiguration {}
</code>

3. Practical Example – AOP Timing Starter

The example demonstrates a starter that records method execution time using Spring AOP.

3.1 Define the aspect

<code>@Aspect
public class TimeAspect {
  @Pointcut("@annotation(time)")
  private void time(RecordTime time) {}

  @Around("time(time)")
  public Object record(ProceedingJoinPoint pjp, RecordTime time) throws Throwable {
    StopWatch clock = new StopWatch(getClass().getSimpleName());
    Object ret = null;
    try {
      Signature signature = pjp.getSignature();
      clock.start(signature.getDeclaringType().getName() + "#" + signature.getName());
      ret = pjp.proceed();
      return ret;
    } finally {
      clock.stop();
      System.out.printf("Execution time: %s%n", clock.prettyPrint());
    }
  }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RecordTime {
  String value() default "";
}
</code>

3.2 Auto‑configuration class

<code>@AutoConfiguration
@ConditionalOnProperty(prefix = "pack.aop", name = "enabled", matchIfMissing = false)
public class RecordTimeAutoConfiguration {
  @Bean
  TimeAspect timeAspect() {
    return new TimeAspect();
  }
}
</code>

3.3 Register the starter

Create the file META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports with the following line:

<code>com.component.aop.time.RecordTimeAutoConfiguration</code>

After packaging the starter, add it as a dependency and annotate any method you want to monitor with @RecordTime . The aspect will log the execution duration.

JavaAOPSpring BootAutoConfigurationCustom Starter
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.