Backend Development 10 min read

Master Spring Boot Auto-Configuration: Beans, Conditions, and Custom Starters

This article explains how Spring Boot auto‑configuration works, how to locate candidate configurations, use various @Conditional annotations, and build a custom starter—including naming conventions, property keys, and a complete logging starter example with code snippets.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Boot Auto-Configuration: Beans, Conditions, and Custom Starters

Understanding Auto-Configuration Beans

At the core, Spring Boot auto‑configuration is implemented with standard @Configuration classes, guarded by @Conditional annotations such as @ConditionalOnClass and @ConditionalOnMissingBean to ensure they apply only when the relevant classes are present and no user‑defined configuration exists.

You can inspect the spring-boot-autoconfigure source (see META-INF/spring.factories ) to see the provided @Configuration classes.

Locating Candidate Auto‑Configurations

Spring Boot scans for META-INF/spring.factories in each jar. The file lists configuration classes under the EnableAutoConfiguration key, for example:

<code>org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pack.bus.autoconfigure.BusAutoConfiguration,\
com.pack.bus.autoconfigure.BusWebAutoConfiguration
</code>

Auto‑configuration classes must not be picked up by component scanning; they should be imported explicitly.

Ordering can be controlled with @AutoConfigureAfter , @AutoConfigureBefore or @AutoConfigureOrder . The order only affects bean definition registration, not the actual bean creation order, which is determined by dependencies.

Conditional Annotations

Typical auto‑configuration classes include one or more @Conditional annotations. Common examples are @ConditionalOnMissingBean and the many @Conditional… annotations provided by Spring Boot.

Class Conditions : @ConditionalOnClass , @ConditionalOnMissingClass – include a configuration based on the presence or absence of a class.

Bean Conditions : @ConditionalOnBean , @ConditionalOnMissingBean – include based on the existence of a bean.

Property Conditions : @ConditionalOnProperty – include when a Spring environment property matches criteria.

Resource Conditions : @ConditionalOnResource – include when a specific resource is available.

Web Application Conditions : @ConditionalOnWebApplication , @ConditionalOnNotWebApplication – include based on the type of web application.

War Deployment Condition : @ConditionalOnWarDeployment – include for traditional WAR deployments.

SpEL Expression Condition : @ConditionalOnExpression – include based on a SpEL expression result.

When using class‑level conditions as meta‑annotations, the name attribute must be used to reference classes by name.

Creating Your Own Starter

Naming : Use a distinct namespace; avoid the spring-boot prefix unless you intend official support. Typically a starter is named acme-spring-boot-starter and its auto‑configuration module acme-spring-boot .

Configuration Keys : Keep keys in a unique namespace, not colliding with Spring Boot’s own keys (e.g., server , management ).

Provide Javadoc for each property.

<code>@ConfigurationProperties("acme")
public class AcmeProperties {
  /** Whether to check the location of acme resources. */
  private boolean checkLocation = true;
  /** Timeout for establishing a connection to the acme server. */
  private Duration loginTimeout = Duration.ofSeconds(3);
}
</code>

Full Example – Logging Starter

Auto‑configuration class :

<code>@Configuration
@EnableConfigurationProperties(LogsProperties.class)
@ConditionalOnProperty(prefix = "logs", name = "enabled", havingValue = "true")
@EnableAspectJAutoProxy
public class LogsAutoConfiguration {
  private static final Logger logger = LoggerFactory.getLogger(LogsAutoConfiguration.class);
  @Resource
  private LogsProperties logsProperties;

  @Bean
  public AspectJExpressionPointcutAdvisor logAdvisor() {
    AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
    logger.info("执行表达式:{}", logsProperties.getPointcut());
    advisor.setExpression(logsProperties.getPointcut());
    advisor.setAdvice(new SystemAroundOperator());
    return advisor;
  }
}
</code>

Custom annotation :

<code>@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemLog {
  /** <p>操作说明</p> */
  String value() default "";
}
</code>

Properties class :

<code>@ConfigurationProperties(prefix = "logs")
public class LogsProperties {
  /** 切入点定义<br/> 示例:execution(public * com.pack.controller.*.*(..)) */
  private String pointcut;
  /** 是否开启日志功能 */
  private boolean enabled = true;
}
</code>

Advice implementation :

<code>public class SystemAroundOperator implements MethodInterceptor {

  private static final Logger logger = LoggerFactory.getLogger(SystemAroundOperator.class);

  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable {
    long start = System.currentTimeMillis();
    Method method = invocation.getMethod();
    SystemLog annoLog = null;
    if (method.isAnnotationPresent(SystemLog.class)) {
      annoLog = method.getAnnotation(SystemLog.class);
      String value = annoLog.value();
      try {
        Object result = invocation.proceed();
        Long execTime = System.currentTimeMillis() - start;
        logger.info("{}, 业务执行时间:{} ms", value, execTime);
        return result;
      } catch (Throwable t) {
        Long execTime = System.currentTimeMillis() - start;
        logger.info("{}, 业务执行时间:{} ms,发生异常信息:{}", value, execTime, t.getMessage());
        throw t;
      }
    }
    return invocation.proceed();
  }
}
</code>

Register the auto‑configuration in META-INF/spring.factories :

<code>org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pack.config.LogsAutoConfiguration
</code>

The two images illustrate the auto‑configuration flow.

JavaSpring BootAuto‑ConfigurationCustom StarterConditional Annotations
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.