Understanding Application Lifecycle
1. Understanding Spring Boot Startup Sequence
Boot Startup Phases
- Bootstrap context (if Spring Cloud)
- Create
SpringApplication, deduce web type (servlet/reactive/none)
- Run
ApplicationContextInitializers
- Prepare
Environment (load profiles, properties)
- Print banner
- Create
ApplicationContext
- Apply
BeanFactoryPostProcessors & BeanPostProcessors
- Refresh context → instantiate singletons
- Call
ApplicationRunner / CommandLineRunner
- Publish
ApplicationReadyEvent
2. Using ApplicationRunner and CommandLineRunner
| Interface |
Args Type |
Use Case |
CommandLineRunner |
String[] |
Raw arguments |
ApplicationRunner |
ApplicationArguments |
Parsed options (--name=value) |
Example: Seed data on startup
@Component
public class Seeder implements ApplicationRunner {
private final UserRepository repo;
public Seeder(UserRepository repo) { this.repo = repo; }
@Override public void run(ApplicationArguments args) {
if (args.containsOption("seed")) repo.saveAll(defaults());
}
}
3. Implementing ApplicationContextInitializer
| Use |
Description |
| Pre-refresh tweaks |
Modify environment, register beans before refresh |
| Register |
spring.factories or application.addInitializers(...) |
Example: Inject property source on context init
public class TenantInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override public void initialize(ConfigurableApplicationContext ctx) {
ctx.getEnvironment().getPropertySources()
.addFirst(new MapPropertySource("tenant", Map.of("tenant.id", System.getenv("TENANT"))));
}
}
4. Using SmartLifecycle for Custom Lifecycle Management
| Method |
Purpose |
start() |
Called when context starts |
stop(Runnable) |
Async shutdown callback |
isRunning() |
State query |
getPhase() |
Lower phase = earlier start, later stop |
isAutoStartup() |
Auto-start with context |
5. Handling Application Ready Events (ApplicationReadyEvent)
Example: Warm caches on ApplicationReadyEvent
@Component
public class ReadyHandler {
@EventListener(ApplicationReadyEvent.class)
public void onReady() { /* warm caches, register with discovery */ }
}
Note: Fired after context refresh AND runners — safe place to do work that
requires app fully started.
6. Handling Application Started Events
| Event |
Fired When |
ApplicationStartingEvent |
Run starts, before context |
ApplicationEnvironmentPreparedEvent |
Environment ready |
ApplicationContextInitializedEvent |
After initializers |
ApplicationPreparedEvent |
Context loaded but not refreshed |
ApplicationStartedEvent |
Context refreshed, before runners |
ApplicationReadyEvent |
After runners |
ApplicationFailedEvent |
Startup failure |
7. Handling Context Refresh Events
Example: Handle ContextRefreshedEvent
@EventListener(ContextRefreshedEvent.class)
public void onRefresh(ContextRefreshedEvent e) {
ApplicationContext ctx = e.getApplicationContext();
}
| Event |
Trigger |
ContextRefreshedEvent |
refresh() / actuator refresh |
ContextStartedEvent |
start() called |
ContextStoppedEvent |
stop() called |
ContextClosedEvent |
close() called |
8. Implementing Graceful Shutdown
Example: Graceful shutdown with timeout
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
| Effect |
Description |
| Stop accepting new requests |
Web server returns connections |
| Drain in-flight |
Waits up to timeout-per-shutdown-phase |
| Trigger |
SIGTERM, JVM hook, actuator /shutdown |
9. Using Exit Codes (ExitCodeGenerator)
Example: Custom exit code with ExitCodeGenerator
@SpringBootApplication
public class App {
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(App.class, args),
() -> 42));
}
}
| Element |
Use |
ExitCodeGenerator |
Bean returning exit code |
ExitCodeExceptionMapper |
Map exception → code |
SpringApplication.exit() |
Compute aggregated exit code |
10. Configuring Startup Actuator Endpoint
| Property |
Value |
management.endpoint.startup.enabled |
true |
management.endpoints.web.exposure.include |
startup,health |
spring.main.application-startup |
BufferingApplicationStartup(1024) in main |
Example: Buffer startup steps for /actuator/startup
SpringApplication app = new SpringApplication(App.class);
app.setApplicationStartup(new BufferingApplicationStartup(2048));
app.run(args);