Backend Development 15 min read

Deep Dive into Spring Boot Startup Sequence and Extension Points

This article provides a comprehensive explanation of Spring Boot's startup process, detailing each lifecycle extension point, the order of execution, common pitfalls with RPC/MQ/HTTP traffic, and includes runnable code examples to help developers master Spring initialization.

Top Architect
Top Architect
Top Architect
Deep Dive into Spring Boot Startup Sequence and Extension Points

Although most Java developers spend their time on CRUD operations, understanding the Spring framework's startup mechanism is essential because many middleware components integrate tightly with Spring.

Overview of Spring Startup Order

A long diagram (not shown) illustrates the complete startup sequence, followed by a series of questions designed to test readers' grasp of the process.

When does an RPC framework register services within Spring? Can it be done in init-method ?

When does an MQ consumer start consuming, and which Spring extension point should be used?

How does Spring Boot integrate Tomcat, and when does Tomcat open its port?

Common production incidents occur when traffic (RPC, HTTP, MQ) is started before Spring has fully initialized, leading to missing event listeners and runtime errors.

Key Questions About Spring Initialization

Can getBeanByAnnotation be called accurately in @PostConstruct before Spring is fully started?

How should a project listen for Spring's ready event?

How to listen for the Spring refresh event?

What is the execution order and difference between Spring ready and refresh events?

When does HTTP traffic become available?

Is it reasonable to register RPC or MQ services in init-method ?

What is the correct timing for invoking getBeanByAnnotation ?

Important Spring Extension Points

BeanFactoryAware

ApplicationContextAware

BeanNameAware

ApplicationListener (e.g., ContextRefreshedEvent)

CommandLineRunner

SmartLifecycle#start

@PostConstruct

InitializingBean

XML init-method

@Configuration @Bean registration

BeanPostProcessor (before & after initialization)

BeanFactoryPostProcessor

Code Experiment to Verify Execution Order

Define a class that implements many lifecycle interfaces and log each callback:

public class TestSpringOrder implements ApplicationContextAware,
      BeanFactoryAware,
      InitializingBean,
      SmartLifecycle,
      BeanNameAware,
      ApplicationListener
,
      CommandLineRunner,
      SmartInitializingSingleton {
    // implementation omitted for brevity
}

Add @PostConstruct and an initMethod to the same class:

@PostConstruct
public void postConstruct() {
    log.error("启动顺序:post-construct");
}

public void initMethod() {
    log.error("启动顺序:init-method");
}

Implement a second class to demonstrate BeanPostProcessor and BeanFactoryPostProcessor:

public class TestSpringOrder3 implements BeanPostProcessor, BeanFactoryPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.error("启动顺序:BeanPostProcessor postProcessBeforeInitialization beanName:{}", beanName);
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.error("启动顺序:BeanPostProcessor postProcessAfterInitialization beanName:{}", beanName);
        return bean;
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        log.error("启动顺序:BeanFactoryPostProcessor postProcessBeanFactory ");
    }
}

Running the application produces the following log, showing the exact order of each extension point:

2023-11-25 18:10:53,748 [main] ERROR (TestSpringOrder3:37) - 启动顺序:BeanFactoryPostProcessor postProcessBeanFactory 
2023-11-25 18:10:59,299 [main] ERROR (TestSpringOrder:53) - 启动顺序:构造函数 TestSpringOrder
2023-11-25 18:10:59,316 [main] ERROR (TestSpringOrder:127) - 启动顺序: Autowired
2023-11-25 18:10:59,316 [main] ERROR (TestSpringOrder:129) - 启动顺序:setBeanName
2023-11-25 18:10:59,316 [main] ERROR (TestSpringOrder:111) - 启动顺序:setBeanFactory
2023-11-25 18:10:59,316 [main] ERROR (TestSpringOrder:121) - 启动顺序:setApplicationContext
2023-11-25 18:10:59,316 [main] ERROR (TestSpringOrder3:25) - 启动顺序:BeanPostProcessor postProcessBeforeInitialization beanName:testSpringOrder
2023-11-25 18:10:59,316 [main] ERROR (TestSpringOrder:63) - 启动顺序:post-construct
2023-11-25 18:10:59,317 [main] ERROR (TestSpringOrder:116) - 启动顺序:afterPropertiesSet
2023-11-25 18:10:59,317 [main] ERROR (TestSpringOrder:46) - 启动顺序:init-method
2023-11-25 18:10:59,320 [main] ERROR (TestSpringOrder3:31) - 启动顺序:BeanPostProcessor postProcessAfterInitialization beanName:testSpringOrder
2023-11-25 18:17:21,563 [main] ERROR (SpringOrderConfiguartion:21) - 启动顺序: @Bean 注解方法执行
2023-11-25 18:17:21,668 [main] ERROR (TestSpringOrder:58) - 启动顺序:SmartInitializingSingleton
2023-11-25 18:17:21,675 [main] ERROR (TestSpringOrder:74) - 启动顺序:start
2023-11-25 18:17:23,508 [main] ERROR (TestSpringOrder:68) - 启动顺序:ContextRefreshedEvent
2023-11-25 18:17:23,574 [main] ERROR (TestSpringOrder:79) - 启动顺序:CommandLineRunner

Key Takeaways

• BeanFactoryPostProcessor runs after bean definitions are loaded but before any bean instances are created.

• Autowired injection occurs after bean instantiation and before @PostConstruct , so fields are safe to use there.

• init-method , @PostConstruct , and afterPropertiesSet execute in the order: @PostConstruct → afterPropertiesSet → init-method .

• The safest moment to open RPC, MQ, or HTTP traffic is after SmartInitializingSingleton (or in SmartLifecycle#start ) when all singleton beans and event listeners are fully ready.

• Listening to Spring readiness can be done via SmartLifecycle or ContextRefreshedEvent , while the refresh event itself may fire multiple times and requires idempotent handling.

• Spring Boot only starts the embedded web server after the application context is fully initialized, ensuring HTTP traffic is available at the final stage of startup.

By mastering these lifecycle details, developers can avoid the typical production incidents caused by premature traffic exposure and design more robust Spring Boot applications.

backendJavaSpringLifecycleSpringBootDependencyInjectionstartup
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.