Why Does ApplicationContextInitializer Run Twice? Debugging Spring Boot Startup

This article explains the purpose of ApplicationContextInitializer in Spring Boot, shows how to implement custom conditions and initializers for environment‑specific configuration, and investigates why the initializer may execute twice when Spring Cloud Context is added, leading to bean duplication and port conflicts.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
Why Does ApplicationContextInitializer Run Twice? Debugging Spring Boot Startup

ApplicationContextInitializer Introduction

The initializer works on a ConfigurableApplicationContext (an ApplicationContext) and allows us to enhance the context before the refresh operation.

Business Scenario

In real‑world web applications we often need to programmatically initialize the application context, such as registering property sources (bootstrap/application properties) and dynamically activating different profiles based on the environment. For example, a recent project required loading different SDK parameters depending on whether the OS is Linux or Windows.

Custom Condition Implementation

Because of the large number of configuration items, we can customize @Conditional on a ConfigurationProperties bean.

public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String property = context.getEnvironment().getProperty("os.name");
        // ...
        return property.contains("linux");
    }
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({LinuxCondition.class})
public @interface ConditionOnLinux {}

Due to the SDK’s overly complex configuration classes, this approach was eventually abandoned.

Custom ApplicationContextInitializer Implementation

Based on the context environment, we load resource directories and configuration files for different environments.

public class SelectApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext context) {
        ConfigurableEnvironment env = context.getEnvironment();
        MutablePropertySources mps = env.getPropertySources();
        String property = env.getProperty("os.name");
        if (property.contains("Mac OS X")) {
            mps.addLast(new ResourcePropertySource(new ClassPathResource("linux.properties")));
        } else {
            mps.addLast(new ResourcePropertySource(new ClassPathResource("window.properties")));
        }
    }
}

Problem: initialize Executes Twice

When the functionality is extracted into a starter and runs in a monolithic Spring Boot project, adding Spring Cloud Context causes the initializer to run twice.

SpringApplication.run

To locate the root cause, a breakpoint was set in SpringApplication.run.

BootstrapApplicationListener

The investigation reached the BootstrapApplicationListener.bootstrapServiceContext method.

We examined the bootstrapServiceContext method.

SpringApplicationBuilder builder = (new SpringApplicationBuilder(new Class[0]))
    .profiles(environment.getActiveProfiles())
    .bannerMode(Mode.OFF)
    .environment(bootstrapEnvironment)
    .registerShutdownHook(false)
    .logStartupInfo(false)
    .web(WebApplicationType.NONE);
SpringApplication builderApplication = builder.application();
if (builderApplication.getMainApplicationClass() == null) {
    builder.main(application.getMainApplicationClass());
}
if (environment.getPropertySources().contains("refreshArgs")) {
    builderApplication.setListeners(this.filterListeners(builderApplication.getListeners()));
}
builder.sources(BootstrapImportSelectorConfiguration.class);
ConfigurableApplicationContext context = builder.run(new String[0]);
context.setId("bootstrap");

Truth Warning

Inside BootstrapApplicationListener, SpringApplicationBuilder triggers a restart; although Run is called twice, the first run does not start the container, leading to beans being loaded twice or port conflicts such as Tomcat.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ApplicationContextInitializerspring-bootspring-cloudcustom-condition
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

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.