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.
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.
政采云技术
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.