Careeroza
How SpringApplication Starts
The Startup Sequence
One line in main starts the whole application: SpringApplication.run(ShopEaseApplication.class, args). Behind it, Spring Boot runs a fixed sequence of steps. Knowing them helps you debug slow startups and "bean not found" errors.
SpringApplication.run(...) | 1. Decide the app type (SERVLET / REACTIVE / NONE) from the classpath 2. Load ApplicationContextInitializers and ApplicationListeners (META-INF/spring.factories) 3. Prepare the Environment: application.yml, profiles, env vars, command-line args 4. Print the banner 5. Create the ApplicationContext (AnnotationConfigServletWebServerApplicationContext) 6. Load bean definitions: your @Component classes + auto-configuration classes 7. Refresh the context: create singletons, inject dependencies, run @PostConstruct 8. Start the embedded web server (Tomcat on port 8080) 9. Call CommandLineRunner / ApplicationRunner beans 10. Publish ApplicationReadyEvent -> "Started ShopEaseApplication in 2.1 seconds"
Hooking Into Startup
@SpringBootApplication
public class ShopEaseApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(ShopEaseApplication.class);
app.setBannerMode(Banner.Mode.OFF); // customise before run
app.run(args);
}
@Bean
ApplicationRunner warmUp(ProductRepository products) {
return args -> System.out.println("Products in DB: " + products.count());
}
@EventListener(ApplicationReadyEvent.class)
void ready() {
System.out.println("ShopEase is ready to take orders");
}
}Example
Run it and watch the log:
./mvnw spring-boot:runExample output
INFO o.s.b.w.e.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) INFO o.s.b.w.e.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/' INFO c.s.ShopEaseApplication : Started ShopEaseApplication in 2.134 seconds (process running for 2.51) Products in DB: 42 ShopEase is ready to take orders
Simulating the Lifecycle in Plain Java
Example
A tiny "container" that runs the same phases in the same order. Real Spring is much bigger, but the order is identical:
import java.util.*;
import java.util.function.*;
public class Main {
public static void main(String[] args) {
MiniApp app = new MiniApp();
app.register("productRepository", () -> new Bean("productRepository"));
app.register("productService", () -> new Bean("productService"));
app.addRunner(() -> System.out.println("CommandLineRunner: loading demo products"));
app.run();
}
}
class Bean {
final String name;
Bean(String name) { this.name = name; System.out.println(" create " + name); }
void postConstruct() { System.out.println(" init " + name + " (@PostConstruct)"); }
}
class MiniApp {
private final Map<String, Supplier<Bean>> definitions = new LinkedHashMap<>();
private final List<Runnable> runners = new ArrayList<>();
void register(String name, Supplier<Bean> s) { definitions.put(name, s); }
void addRunner(Runnable r) { runners.add(r); }
void run() {
System.out.println("1. prepare environment (profile=dev)");
System.out.println("2. load " + definitions.size() + " bean definitions");
System.out.println("3. refresh context:");
definitions.values().forEach(s -> s.get().postConstruct());
System.out.println("4. start web server on port 8080");
runners.forEach(Runnable::run);
System.out.println("5. ApplicationReadyEvent published");
}
}Output
1. prepare environment (profile=dev) 2. load 2 bean definitions 3. refresh context: create productRepository init productRepository (@PostConstruct) create productService init productService (@PostConstruct) 4. start web server on port 8080 CommandLineRunner: loading demo products 5. ApplicationReadyEvent published
Practice
Exercise: Add a bean that prints "Cache warmed" after the application is fully ready (not during bean creation).
Show answer
@Component
class CacheWarmer {
@EventListener(ApplicationReadyEvent.class)
void warm() {
System.out.println("Cache warmed");
}
}