RadhaPublication
HomeInterviewLearning PathsRole TracksMockBooksPricing
Login / Sign UpLog in

© 2026 Radha Publication. All rights reserved.

Shop on AmazonDonateContactPrivacyTerms
Spring Boot questions
EasySpring Boot#67 min readJul 11, 2026

What is SpringApplication.run()?

practice
learning
Practice modeTest yourself instead of reading straight through

Hook: This is the one line that turns a plain Java class into a live Spring Boot app, which is why interviewers love it.

Question: What is SpringApplication.run()?

Answer: SpringApplication.run() is the main startup method in Spring Boot. It creates the Spring application context, applies auto-configuration, scans and wires beans, and starts the embedded web server if the app is a web app. It also processes command-line arguments and returns the running context so you can access beans after startup.

Interview-Ready Answer: I use SpringApplication.run() as the bootstrap call that launches a Spring Boot app. It builds and refreshes the application context, loads beans, applies auto-configuration, and starts the embedded server when needed. It also returns the live context, so after startup I can still inspect or use beans, which is a nice detail interviewers often like to hear.

🧠 Memory Map
Memory map — visual summary of this topic

What it is

SpringApplication.run() is the convenience entry point for a Spring Boot app. Think of it as the method that takes your application class and launch arguments, then performs the whole bootstrapping sequence for you. The key idea is that it does startup orchestration for the app, not business logic.

How it works under the hood

  1. Create the bootstrapping object. Spring Boot creates a SpringApplication instance from your primary source class, usually the class marked with @SpringBootApplication.
  2. Prepare the Environment. Spring reads command-line arguments, system properties, environment variables, and property files such as application.properties or application.yml. This is where profile-specific config like application-dev.yml can take effect.
  3. Choose the app type. Boot checks the classpath and decides whether the app is servlet-based, reactive, or non-web. If you have Spring MVC and an embedded server dependency, it starts as a servlet web app by default.
  4. Create the ApplicationContext. The application context is the container that holds beans, resolves dependency injection, and manages lifecycle. In simple words, it is the object graph and runtime brain of the app.
  5. Load configuration and beans. Boot processes component scanning, @Configuration classes, and auto-configuration. Auto-configuration is Boot’s smart default setup that turns on useful beans based on what it finds on the classpath and in properties.
  6. Refresh the context. This is the moment Spring actually creates singleton beans, injects dependencies, runs post-processors, and makes the app ready to use.
  7. Start the server if needed. For a web app, Boot starts the embedded server such as Tomcat, Jetty, or Netty. For a non-web app, it just keeps the context alive for background work or command-line tasks.
  8. Run startup callbacks. After refresh, Boot runs CommandLineRunner and ApplicationRunner beans, then publishes ready events. Finally, run() returns the live context object.

Why and when to use it

Use SpringApplication.run() in almost every standard Spring Boot application. It is the normal entry point for REST APIs, MVC apps, batch-like command apps, and many internal services. You usually do not use it inside unit tests, because tests typically load a smaller slice of the app or a test context instead.

run() vs other startup options

OptionBest forKey idea
SpringApplication.run()Most appsFastest, standard bootstrap
SpringApplicationBuilderCustom startupFluent setup, parent-child contexts, more control
Manual context creationLow-level needsYou wire more yourself; Boot magic is reduced

The table matters because interviewers often want to know whether you understand the difference between the simple default path and the custom path. For most production code, the static run() call is enough. Reach for the builder only when you need special context hierarchy, custom listeners, or a very tailored boot sequence.

Performance and edge cases

Startup time is not constant; it grows with the number of beans, the amount of classpath scanning, and how much auto-configuration the app triggers. A small Boot service might start in under 2 seconds on a warm machine, while a larger service can take 5 to 15 seconds cold depending on dependencies and hardware. Memory usage at startup is often in the 100 to 300 MB range for a typical service, but this varies a lot.

Important edge cases:

  • If startup fails, run() throws an exception and the process exits with a non-zero code.
  • If you accidentally run two apps on the same port, the second one fails fast with a port-in-use error.
  • If your package structure is too narrow or your scan path is wrong, Spring may not find the beans you expect.
  • If you pass a bad startup property, the failure usually happens before the server accepts traffic, which is a good fail-fast behavior.

Memory hook: think of SpringApplication.run() as the stage manager for a show: it sets the lights, opens the curtains, and hands you the live stage after everything is ready.

Real-world story

Imagine an e-commerce checkout service. On deploy, SpringApplication.run() reads the payment gateway settings, creates the checkout beans, starts embedded Tomcat, and then the service becomes ready for traffic. If a secret is missing or a database URL is wrong, the app never becomes healthy, which is exactly what you want in production.

What goes wrong: a team sets an invalid property for the database connection, so startup fails during bean creation. In Kubernetes, the pod keeps restarting, logs show Application run failed, readiness probes never pass, and customers cannot place orders. From the outside it looks like a complete outage, but the root cause is usually one boot-time configuration mistake.

That is why understanding run() matters: it is not just a method call, it is the point where config mistakes become visible before the app starts serving real users.

Spring Boot
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        // SpringApplication.run() does the bootstrapping work:
        // it prepares the environment, creates the context, starts the embedded server,
        // and returns the live application context.
        ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);

        // This shows the practical value of the return type: you can inspect the running app.
        System.out.println("Bean count after startup: " + context.getBeanDefinitionCount());
    }

    @Bean
    CommandLineRunner startupChecks(ApplicationArguments arguments) {
        return args -> {
            // Edge case / failure path:
            // If a bad startup flag is passed, fail fast instead of letting the app run in a broken state.
            if (arguments.containsOption("fail-startup")) {
                throw new IllegalStateException("Startup aborted because --fail-startup was provided.");
            }

            System.out.println("Non-option args: " + arguments.getNonOptionArgs());
            System.out.println("Option names: " + arguments.getOptionNames());
        };
    }

    @Bean
    GreetingService greetingService() {
        return new GreetingService();
    }

    @RestController
    static class HelloController {
        private final GreetingService greetingService;

        HelloController(GreetingService greetingService) {
            this.greetingService = greetingService;
        }

        @GetMapping("/hello")
        ResponseEntity<String> hello(@RequestParam(defaultValue = "world") String name) {
            // A safe default keeps the endpoint easy to call after the app has started.
            return ResponseEntity.ok(greetingService.greet(name));
        }

        @GetMapping("/divide")
        ResponseEntity<String> divide(@RequestParam int x, @RequestParam int y) {
            // Small error-handling example: a bad request should not become a server crash.
            if (y == 0) {
                return ResponseEntity.badRequest().body("y must not be 0");
            }
            return ResponseEntity.ok(String.valueOf(x / y));
        }
    }

    static class GreetingService {
        String greet(String name) {
            return "Hello, " + name + "!";
        }
    }
}

Follow-up & Tricky Questions:

  • What does SpringApplication.run() return? It returns a running ApplicationContext object, usually a ConfigurableApplicationContext, so you can access beans or close the app if needed.
  • Does run() block? Yes, it blocks until startup is complete. For a web app, the main thread finishes startup and then the embedded server handles requests on its own threads.
  • How does it handle command-line arguments? It makes them available to Spring and to startup callbacks like ApplicationRunner and CommandLineRunner, and some args can override config properties.
  • What happens if startup fails? Spring prints startup failure details, closes any partially created context, and rethrows the error so the process exits instead of running half-broken.
  • Can I customize the bootstrap process? Yes. You can use SpringApplication settings, listeners, profiles, or SpringApplicationBuilder when you need more control than the one-line default.

Tricky / gotcha questions:

  • Is SpringApplication.run() the same as main()? No. main() is just the Java entry point; run() is the Spring Boot bootstrap engine that actually starts the app.
  • Does it always start a web server? No. Only web applications with the right dependencies start an embedded server; non-web apps can start a context without Tomcat, Jetty, or Netty.
  • Does run() automatically find every class on the classpath? No. It uses component scanning and auto-configuration rules, so package structure and annotations still matter a lot.

Common Mistakes:

  • Thinking it only starts web apps. Correction: it can start web or non-web Spring Boot applications; the embedded server is only started when the app type needs it.
  • Confusing it with business logic. Correction: run() is startup plumbing, not a place for application rules or request handling.
  • Forgetting that it returns a context. Correction: the return value is useful for inspection, closing resources, or accessing beans after startup.
  • Assuming startup errors are ignored. Correction: Boot fails fast, which is exactly what you want when config or bean creation is broken.

Memory Hook: main() turns the key, and SpringApplication.run() drives the car onto the road.

Cheat Sheet:

  • It is the standard Spring Boot bootstrap method.
  • It creates and refreshes the application context.
  • It loads beans, config, and auto-configuration.
  • It starts the embedded server for web apps.
  • It returns the live context.
  • It fails fast when startup is broken.

Practice Tasks:

  • Add a second REST endpoint and confirm it becomes available only after the app starts.
  • Run the app with --fail-startup and observe how Spring Boot stops before serving traffic.
  • Print the bean count or inspect the returned context to see what Boot created for you.
Previous
Back to Questions←→to navigate
Next

Recommended Resources

Recommended Book

Cracking the Coding Interview

189 Programming Questions and Solutions

Recommended Book

Cracking the Coding Interview

189 Programming Questions and Solutions

import org.springframework.boot.ApplicationArguments; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { // SpringApplication.run() does the bootstrapping work: // it prepares the environment, creates the context, starts the embedded server, // and returns the live application context. ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args); // This shows the practical value of the return type: you can inspect the running app. System.out.println("Bean count after startup: " + context.getBeanDefinitionCount()); } @Bean CommandLineRunner startupChecks(ApplicationArguments arguments) { return args -> { // Edge case / failure path: // If a bad startup flag is passed, fail fast instead of letting the app run in a broken state. if (arguments.containsOption("fail-startup")) { throw new IllegalStateException("Startup aborted because --fail-startup was provided."); } System.out.println("Non-option args: " + arguments.getNonOptionArgs()); System.out.println("Option names: " + arguments.getOptionNames()); }; } @Bean GreetingService greetingService() { return new GreetingService(); } @RestController static class HelloController { private final GreetingService greetingService; HelloController(GreetingService greetingService) { this.greetingService = greetingService; } @GetMapping("/hello") ResponseEntity<String> hello(@RequestParam(defaultValue = "world") String name) { // A safe default keeps the endpoint easy to call after the app has started. return ResponseEntity.ok(greetingService.greet(name)); } @GetMapping("/divide") ResponseEntity<String> divide(@RequestParam int x, @RequestParam int y) { // Small error-handling example: a bad request should not become a server crash. if (y == 0) { return ResponseEntity.badRequest().body("y must not be 0"); } return ResponseEntity.ok(String.valueOf(x / y)); } } static class GreetingService { String greet(String name) { return "Hello, " + name + "!"; } } }