Spring Boot

Published on: 26 November 2025

Tags: #spring-boot #java


The Spring Boot Startup Lifecycle (SpringApplication.run)

sequenceDiagram
    autonumber
    participant Main as Main Method
    participant SA as SpringApplication
    participant SARL as SpringApplicationRunListeners
    participant Env as ConfigurableEnvironment
    participant Ctx as ApplicationContext
    participant BF as BeanFactory
    participant Auto as AutoConfigImportSelector
    participant Embed as EmbeddedWebServer

    Main->>SA: run(primarySources, args)
    activate SA

    Note right of SA: 1. Bootstrap Phase
    SA->>SA: Create BootstrapContext
    SA->>SARL: starting()

    Note right of SA: 2. Prepare Environment
    SA->>SA: configureEnvironment()
    SA->>Env: Load Properties (application.properties)
    SA->>SARL: environmentPrepared(environment)

    Note right of SA: 3. Create Context
    SA->>SA: createApplicationContext()

    Note right of SA: 4. Prepare Context
    SA->>SA: applyInitializers()
    SA->>SARL: contextPrepared(context)
    SA->>SA: load(primarySources)
    SA->>SARL: contextLoaded(context)

    Note right of SA: 5. Refresh Context (The Critical Path)
    SA->>Ctx: refresh()
    activate Ctx

    rect rgb(255, 250, 240)
        note right of Ctx: Phase 5a: Bean Definitions
        Ctx->>BF: invokeBeanFactoryPostProcessors()

        Note over Ctx, Auto: Parsing @EnableAutoConfiguration
        Ctx->>Auto: selectImports()
        Auto-->>Ctx: List of Config Class Names

        Ctx->>BF: registerBeanPostProcessors()
        Ctx->>BF: initMessageSource()
    end

    rect rgb(240, 248, 255)
        note right of Ctx: Phase 5b: Web Server Creation
        Ctx->>Ctx: onRefresh()
        Ctx->>Embed: createWebServer() (Tomcat init)
        Note left of Embed: Server created but NOT started
    end

    rect rgb(255, 240, 245)
        note right of Ctx: Phase 5c: Bean Instantiation
        Ctx->>Ctx: finishBeanFactoryInitialization()
        Note over Ctx: Instantiate Singletons (Non-Lazy)
    end

    rect rgb(240, 255, 240)
        note right of Ctx: Phase 5d: Finalize
        Ctx->>Ctx: finishRefresh()
        Ctx->>Embed: start()
        activate Embed
        Note left of Embed: Port 8080 listening
    end

    deactivate Ctx

    SA->>SARL: started(context)
    SA->>SA: callRunners (CommandLineRunner)
    SA->>SARL: running(context)

    deactivate SA

Auto-Configuration

flowchart TD
    Start([App Startup]) --> Scan["@EnableAutoConfiguration"]

    Scan --> Load["Load candidates from:
META-INF/spring/...AutoConfiguration.imports"] Load --> Candidates["List of Candidate Config Class Names"] Candidates --> Deduplicate["Deduplicate & Remove Exclusions"] Deduplicate --> Sort["Sort Candidates
(@AutoConfigureOrder / Before / After)"] Sort --> Iterate subgraph FilterProcess [Condition Evaluation Loop] direction TB Iterate[Iterate Config Class X] --> CondClass{"@ConditionalOnClass?"} CondClass -- Class Missing --> Discard[Discard Configuration] CondClass -- Class Present --> CondProp{"@ConditionalOnProperty?"} CondProp -- Prop=false --> Discard CondProp -- Prop=true --> CondWeb{"@ConditionalOnWebApplication?"} CondWeb -- Mismatch --> Discard CondWeb -- Match --> Register[Register Configuration Class] end Register --> BeanPhase[Process @Bean Methods] subgraph BeanLogic [Inside the Configuration Class] BeanPhase --> CondBean{"@ConditionalOnMissingBean?"} CondBean -- Bean Already Exists --> SkipBean[Skip creating this specific Bean] CondBean -- No Bean Found --> RegBean[Register BeanDefinition] end RegBean --> End([Ready for DI]) SkipBean --> End style FilterProcess fill:#f9f9f9,stroke:#333,stroke-width:2px style BeanLogic fill:#f0f8ff,stroke:#333,stroke-dasharray: 5 5 style Discard fill:#ffcccc,stroke:#333 style RegBean fill:#ccffcc,stroke:#333

MVC Request Flow

sequenceDiagram
    participant Client
    participant Container as Servlet Container
    participant Filter as Servlet Filters
    participant DS as DispatcherServlet
    participant INT as HandlerInterceptors
    participant HA as HandlerAdapter
    participant RVH as ReturnValueHandler
(RequestResponseBodyMethodProcessor) participant MSG as HttpMessageConverter Client->>Container: HTTP GET /api/users Container->>Filter: doFilter() Filter->>DS: doService() -> doDispatch() activate DS DS->>DS: getHandler(request) (returns Chain) DS->>DS: getHandlerAdapter(handler) DS->>INT: preHandle() alt preHandle returns true DS->>HA: handle(request, response, handler) activate HA HA->>HA: Invoke Controller Method note right of HA: Business Logic Execution HA->>RVH: handleReturnValue(UserObject) activate RVH Note right of RVH: Handles @ResponseBody RVH->>MSG: write(UserObject, Type, Response) activate MSG MSG->>MSG: Serialize to JSON MSG-->>Container: Write bytes to Response OutputStream note left of MSG: Response Committed here! deactivate MSG RVH-->>HA: return deactivate RVH HA-->>DS: Return null ModelAndView note right of HA: MAV is null because response is committed deactivate HA DS->>INT: applyPostHandle() note right of INT: Called, but cannot change Response else preHandle returns false DS-->>Client: Request blocked end DS->>INT: triggerAfterCompletion() DS-->>Filter: return deactivate DS Filter-->>Container: return Container-->>Client: HTTP 200 OK (JSON Body)

Bean Lifecycle

flowchart TD
    Start((Start)) --> Instantiate["1. Instantiation
Constructor Call"] subgraph Pop [2. Population & Aware] direction TB Instantiate --> DI["Dependency Injection
Setters / Fields"] DI --> BName["BeanNameAware"] BName --> BFactory["BeanFactoryAware"] BFactory --> AppCtx["ApplicationContextAware
*Applied via BPP*"] end subgraph Init [3. Initialization] direction TB AppCtx --> BPPBefore[BeanPostProcessor
.postProcessBeforeInitialization] BPPBefore --> PostConstruct[annotation @PostConstruct] PostConstruct --> InitBean["InitializingBean
.afterPropertiesSet()"] InitBean --> CustomInit[Custom init-method] CustomInit --> BPPAfter[BeanPostProcessor
.postProcessAfterInitialization] end subgraph ProxyPhase [4. The AOP Magic] direction TB BPPAfter --> IsAOP{Has @Transactional
@Async / @Cacheable?} IsAOP -- Yes --> CreateProxy[Wrap Bean in CGLIB/JDK Proxy] IsAOP -- No --> ReturnRaw[Keep Raw Bean Instance] end CreateProxy --> Ready([Bean Ready in Container]) ReturnRaw --> Ready Ready --> Stop((App Shutdown)) subgraph Destroy [5. Destruction] direction TB Stop --> PreDestroy[annotation @PreDestroy] PreDestroy --> DispBean["DisposableBean
.destroy()"] DispBean --> CustomDestroy[Custom destroy-method] end CustomDestroy --> End((End)) style ProxyPhase fill:#fff0f5,stroke:#333,stroke-dasharray: 5 5 style CreateProxy fill:#ffcc00,stroke:#333 style Ready fill:#ccffcc,stroke:#333

Share this post

Share on X  •  Share on LinkedIn  •  Share via Email