How to Accurately Measure Spring Boot Bean Creation Time for Performance Optimization

This article demonstrates a non‑intrusive, high‑precision method to track each Spring Boot bean's creation time by customizing ApplicationContextFactory, Environment, and BeanFactory, allowing package‑level exclusion and clear console reporting to pinpoint slow‑loading beans during startup.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How to Accurately Measure Spring Boot Bean Creation Time for Performance Optimization

In Spring Boot startup optimization, bean creation time can be a critical bottleneck. Traditional monitoring cannot precisely measure each bean's instantiation and initialization, nor separate the time spent on dependent beans. The article presents a non‑intrusive, high‑precision approach that customizes ApplicationContextFactory, Environment, and BeanFactory, supports package‑exclude configuration, and provides clear console output for slow‑loading beans.

Custom ApplicationContextFactory

@Order(Ordered.HIGHEST_PRECEDENCE)
public class PackServletWebServerApplicationContextFactory implements ApplicationContextFactory {
    @Override
    public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
        return (webApplicationType != WebApplicationType.SERVLET) ? null : PackApplicationServletEnvironment.class;
    }
    @Override
    public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
        return (webApplicationType != WebApplicationType.SERVLET) ? null : new PackApplicationServletEnvironment();
    }
    @Override
    public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
        return (webApplicationType != WebApplicationType.SERVLET) ? null : createContext();
    }
    private ConfigurableApplicationContext createContext() {
        PackListableBeanFactory beanFactory = new PackListableBeanFactory();
        if (!AotDetector.useGeneratedArtifacts()) {
            AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(beanFactory);
            beanFactory.setContext(context);
            return context;
        }
        ServletWebServerApplicationContext context = new ServletWebServerApplicationContext(beanFactory);
        beanFactory.setContext(context);
        return context;
    }
}

Configure the factory in META-INF/spring.factories:

org.springframework.boot.ApplicationContextFactory=\
com.pack.PackServletWebServerApplicationContextFactory

Custom Environment

public class PackApplicationServletEnvironment extends StandardServletEnvironment {
    @Override
    protected String doGetActiveProfilesProperty() { return null; }
    @Override
    protected String doGetDefaultProfilesProperty() { return null; }
    @Override
    protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {
        return ConfigurationPropertySources.createPropertyResolver(propertySources);
    }
}

Custom BeanFactory

public class PackListableBeanFactory extends DefaultListableBeanFactory {
    private static final Map<String, Long> beanCreationTimeMap = new ConcurrentHashMap<>();
    private ApplicationContext context;
    private volatile boolean initialized = false;
    private List<String> exclude = new ArrayList<>();

    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        if (!initialized) {
            Binder.get(this.context.getEnvironment()).bind("pack.statistics.exclude", Bindable.ofInstance(exclude));
            initialized = true;
        }
        Class<?> beanClass = resolveBeanClass(mbd, beanName);
        if (beanClass == null) {
            beanClass = mbd.getTargetType();
        }
        for (String pkg : exclude) {
            if (beanClass.getPackageName().startsWith(pkg)) {
                return super.createBean(beanName, mbd, args);
            }
        }
        long start = System.nanoTime();
        Object bean = super.createBean(beanName, mbd, args);
        long end = System.nanoTime();
        double durationMillis = (end - start) / 1_000_000.0;
        beanCreationTimeMap.put(beanName, end - start);
        System.out.printf("Bean [%s] created in %.2f ms%n", beanName, durationMillis);
        return bean;
    }

    public void setContext(ApplicationContext context) { this.context = context; }
}

Test Scenario

@Configuration
public class CustomConfig {
    @Bean
    Date aaaa() {
        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
        return new Date();
    }
}

@Component
public class B {
    @PostConstruct
    public void init() {
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
    }
}

After starting the container, the console prints the creation times (image below).

Adding Dependency Between Beans

@Component
public class B {
    @Resource
    private Date aaaa;
    @PostConstruct
    public void init() {
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) {}
    }
}

Running the modified setup produces a new console output (image below) showing the combined timing.

Further Precision

If you need to exclude the time spent on injecting other dependencies, you can override additional methods in the custom factory to isolate pure bean instantiation cost.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

performance optimizationSpring Bootapplicationcontextfactorybean-creation-timecustom-beanfactory
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

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.