Backend Development 5 min read

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.

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

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.

<code>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")));
        }
    }
}
</code>

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.

<code>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");
</code>

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.

debuggingSpring Cloudapplicationcontextinitializerspring-bootcustom-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

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.