Backend Development 9 min read

Master Spring Boot 3 Extension Points: Custom AutoConfiguration, ApplicationContext, and RunListeners

This article walks through Spring Boot 3's powerful extension points—including AutoConfigurationImportFilter, ApplicationContextFactory, SpringApplicationRunListener, and ApplicationContextInitializer—showing how to implement, register, and test custom behavior with complete code examples and configuration steps.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Boot 3 Extension Points: Custom AutoConfiguration, ApplicationContext, and RunListeners

Environment: SpringBoot 3.2.5

1. Introduction

Spring Boot offers many powerful extension points that allow developers to intervene at key moments in the application lifecycle to implement custom logic. The article covers the following extension points:

AutoConfigurationImportFilter – limits auto‑configuration classes.

ApplicationContextFactory – creates the ApplicationContext used by SpringApplication.

SpringApplicationRunListener – defines events triggered at different startup stages.

ApplicationContextInitializer – runs before the container refresh to configure the context.

2. Practical Examples

2.1 AutoConfigurationImportFilter

By default Spring Boot provides three implementations: OnBeanCondition, OnClassCondition, and OnWebApplicationCondition. A custom implementation can be created as follows:

<code>public class PackClassCondition implements AutoConfigurationImportFilter, EnvironmentAware {
  private Environment environment;
  @Override
  public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
    boolean[] matchs = new boolean[autoConfigurationClasses.length];
    for (int i = 0, len = matchs.length; i < len; i++) {
      if (autoConfigurationClasses[i] != null && autoConfigurationClasses[i].equals(PackAutoConfiguration.class.getName())) {
        Boolean ret = this.environment.getProperty("pack.app.enabled", Boolean.class, false);
        matchs[i] = ret;
      } else {
        matchs[i] = true;
      }
    }
    return matchs;
  }
  @Override
  public void setEnvironment(Environment environment) {
    this.environment = environment;
  }
}
</code>

The filter checks whether the current class is PackAutoConfiguration and activates the auto‑configuration only when the property pack.app.enabled is true. Register it in META-INF/spring.factories :

<code>org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
com.pack.extension.autoImportfilter.PackClassCondition
</code>

2.2 ApplicationContextFactory

This interface creates the ApplicationContext required by Spring Boot. A custom factory can decide which context to create based on the environment:

<code>public class PackApplicationContextFactory implements ApplicationContextFactory {
  @Override
  public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
    return (webApplicationType != WebApplicationType.SERVLET) ? null : createContext();
  }
  private ConfigurableApplicationContext createContext() {
    System.err.println("使用自定义容器...");
    return new PackApplicationContext();
  }
  public static class PackApplicationContext extends AnnotationConfigServletWebServerApplicationContext {
    @Override
    protected void prepareRefresh() {
      System.err.println("准备执行容器核心方法refresh");
      super.prepareRefresh();
    }
  }
}
</code>

Register the factory in META-INF/spring.factories :

<code>org.springframework.boot.ApplicationContextFactory=\
com.pack.extension.contextfactory.PackApplicationContextFactory
</code>

Running the application shows the custom ApplicationContext in use.

2.3 SpringApplicationRunListener

The interface defines callbacks for various startup phases. A simple custom listener can log messages at each stage:

<code>public class PackSpringApplicationRunListener implements SpringApplicationRunListener, Ordered {
  @Override
  public int getOrder() { return 1; }
  @Override
  public void contextPrepared(ConfigurableApplicationContext context) {
    System.err.println("ApplicationContext 创建并准备好, 还没有开始调用refresh方法");
  }
  @Override
  public void started(ConfigurableApplicationContext context, Duration timeTaken) {
    System.err.printf("上下文已经被刷新,并且应用程序已经启动,但 *Runners 尚未被调用, 应用程序启动所花费时间: %dms%n", timeTaken.toMillisPart());
  }
}
</code>

Register it in META-INF/spring.factories :

<code>org.springframework.boot.SpringApplicationRunListener=\
com.pack.extension.eventpublisher.PackSpringApplicationRunListener
</code>

The listener can receive the SpringApplication instance and command‑line arguments via a constructor:

<code>private SpringApplication app;
private final String[] args;
public PackSpringApplicationRunListener(SpringApplication app, String[] args) {
  this.app = app;
  this.args = args;
  System.err.printf("%s%s%n", app, Arrays.toString(this.args));
}
</code>

Run the application with:

<code>java -jar App.jar --pack.title=xxxooo --pack.version=1.0.0
</code>

2.4 ApplicationContextInitializer

This interface allows configuration before the container refresh. Example:

<code>public class PackApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
  @Override
  public void initialize(ConfigurableApplicationContext context) {
    context.addApplicationListener(null);
    context.addBeanFactoryPostProcessor(null);
    context.getEnvironment().getConversionService().addConverter(null);
    // ...
  }
}
</code>

Register it in META-INF/spring.factories :

<code>org.springframework.context.ApplicationContextInitializer=\
com.pack.extension.contextinitializer.PackApplicationContextInitializer
</code>

The article demonstrates how to customize Spring Boot's startup process by implementing and registering these extension points, providing complete code snippets and configuration details.

Spring BootExtension PointsApplicationContextFactoryAutoConfigurationImportFilterSpringApplicationRunListener
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.