Backend Development 11 min read

SpringBoot Application Startup Optimization Techniques

This article explains how to analyze and accelerate SpringBoot startup by profiling with tools like Async Profiler, refactoring heavy business code, leveraging BeanPostProcessor for bean initialization metrics, using Spring's context indexer, and applying lazy initialization to reduce launch time in large Java backend services.

政采云技术
政采云技术
政采云技术
SpringBoot Application Startup Optimization Techniques

Startup Time Analysis

To understand the boot time, set the log level to debug and examine the logs, or use profiling tools such as Async Profiler and JProfiler . In IntelliJ IDEA you can run the project with Run *** with Async Profiler to generate a flame graph that shows which methods consume the most time.

Business Code Optimization

Most latency comes from large business logic and heavy initialization (e.g., database connections, Redis pools, MQ producers/consumers, Dubbo services, scheduled tasks). Reduce unnecessary dependencies and make initialization asynchronous when possible. For code that must run at startup, avoid long‑running @PostConstruct methods because they block the main thread.

Startup‑time Business Code Adjustments

After the application context is ready, you can execute code via ApplicationRunner or CommandLineRunner . Implement the run() method in a @Component bean, and control execution order with @Order or by implementing Ordered .

Loading Optimization

Spring provides a BeanPostProcessor with two callbacks:

postProcessBeforeInitialization : called before each bean's init method.

postProcessAfterInitialization : called after each bean's init method.

@Slf4j
@Component
public class BeanInitMetrics implements BeanPostProcessor, CommandLineRunner {
    private Map
stats = new HashMap<>();
    private List
metrics = new ArrayList<>();

    @Override
    public void run(String... args) throws Exception {
        List
metrics = getMetrics();
        log.info(JSON.toJSONString(metrics));
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        stats.put(beanName, System.currentTimeMillis());
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Long start = stats.get(beanName);
        if (start != null) {
            metrics.add(new Metric(beanName, Math.toIntExact(System.currentTimeMillis() - start)));
        }
        return bean;
    }

    public List
getMetrics() {
        metrics.sort((o1, o2) -> {
            try { return o2.getValue() - o1.getValue(); } catch (Exception e) { return 0; }
        });
        log.info("metrics {}", JSON.toJSONString(metrics));
        return UnmodifiableList.unmodifiableList(metrics);
    }

    @Data
    public static class Metric {
        private String name;
        private Integer value;
        private Date createDate;
        public Metric(String name, Integer value) {
            this.name = name;
            this.value = value;
            this.createDate = new Date();
        }
    }
}

The value field represents the bean initialization time in milliseconds; sorting by this value reveals the most expensive beans.

Spring Context Indexer

Since Spring 5, adding @Indexed and the optional spring-context-indexer dependency generates a static META‑INT/spring.components file at compile time. This file is read by CandidateComponentsIndexLoader , allowing @ComponentScan to load candidates from the index instead of scanning the classpath, dramatically improving startup for large applications.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-indexer</artifactId>
    <optional>true</optional>
</dependency>

All modules must use the indexer; otherwise beans in jars without the generated index may be missed.

Lazy Initialization

SpringBoot 2.2 introduces application‑level lazy loading via the property spring.main.lazy-initialization=true , which defers bean creation until first use, greatly reducing startup time at the cost of slower first access. You can also enable it programmatically:

SpringApplication application = new SpringApplication(ExpertsWebApplication.class);
application.setLazyInitialization(Boolean.TRUE);
application.run(args);
new SpringApplicationBuilder(ExpertsWebApplication.class)
    .lazyInitialization(Boolean.TRUE)
    .build(args)
    .run();

For selective lazy loading, annotate specific beans with @Lazy .

Other Optimizations

Periodically clean up dead code and consider splitting monolithic services.

Initialize heavy scheduled tasks or MQ consumers asynchronously after the application has started.

These suggestions aim to reduce the time spent loading beans and initializing resources during SpringBoot startup.

Recruitment Notice

The Zero team in Hangzhou is hiring developers with experience in cloud‑native, blockchain, AI, low‑code platforms, middleware, big data, and more. Interested candidates can email zcy‑tc@cai‑inc.com.

Performancestartup optimizationSpringBootLazy InitializationBeanPostProcessor
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

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.