# Spring Boot 4.1.2 sources: the order SpringApplication.run() calls things in, and callRunners --- SpringApplication.run(): from refresh to ready (lines containing the calls) --- 18: refreshContext(context); 19: afterRefresh(context, applicationArguments); 24: listeners.started(context, timeTakenToStarted); 25: callRunners(context, applicationArguments); 28: throw handleRunFailure(context, ex, listeners); 32: listeners.ready(context, startup.ready()); 36: throw handleRunFailure(context, ex, null); --- SpringApplication.callRunners --- private void callRunners(ConfigurableApplicationContext context, ApplicationArguments args) { ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); String[] beanNames = beanFactory.getBeanNamesForType(Runner.class); Map instancesToBeanNames = new IdentityHashMap<>(); for (String beanName : beanNames) { instancesToBeanNames.put(beanFactory.getBean(beanName, Runner.class), beanName); } Comparator comparator = getOrderComparator(beanFactory) .withSourceProvider(new FactoryAwareOrderSourceProvider(beanFactory, instancesToBeanNames)); instancesToBeanNames.keySet().stream().sorted(comparator).forEach((runner) -> callRunner(runner, args)); } --- SpringApplication.callRunner (what happens to a bean that is both kinds) --- private void callRunner(Runner runner, ApplicationArguments args) { if (runner instanceof ApplicationRunner) { callRunner(ApplicationRunner.class, runner, (applicationRunner) -> applicationRunner.run(args)); } if (runner instanceof CommandLineRunner) { callRunner(CommandLineRunner.class, runner, (commandLineRunner) -> commandLineRunner.run(args.getSourceArgs())); } } --- SpringApplication.callRunner(Class, Runner, ThrowingConsumer) (where 'Failed to execute' comes from) --- private void callRunner(Class type, Runner runner, ThrowingConsumer call) { call.throwing( (message, ex) -> new IllegalStateException("Failed to execute " + ClassUtils.getShortName(type), ex)) .accept((R) runner); } --- EventPublishingRunListener.started / ready --- public void started(ConfigurableApplicationContext context, @Nullable Duration timeTaken) { context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context, timeTaken)); AvailabilityChangeEvent.publish(context, LivenessState.CORRECT); } public void ready(ConfigurableApplicationContext context, @Nullable Duration timeTaken) { context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context, timeTaken)); AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC); } --- the marker interface that both runners extend --- interface Runner { public interface CommandLineRunner extends Runner { public interface ApplicationRunner extends Runner { --- the same method in Spring Boot 3.0.13 --- private void callRunners(ApplicationContext context, ApplicationArguments args) { context.getBeanProvider(Runner.class).orderedStream().forEach((runner) -> { if (runner instanceof ApplicationRunner applicationRunner) { callRunner(applicationRunner, args); } if (runner instanceof CommandLineRunner commandLineRunner) { callRunner(commandLineRunner, args); } }); } --- the same method in Spring Boot 3.1.12 --- private void callRunners(ConfigurableApplicationContext context, ApplicationArguments args) { ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); String[] beanNames = beanFactory.getBeanNamesForType(Runner.class); Map instancesToBeanNames = new IdentityHashMap<>(); for (String beanName : beanNames) { instancesToBeanNames.put(beanFactory.getBean(beanName, Runner.class), beanName); } Comparator comparator = getOrderComparator(beanFactory) .withSourceProvider(new FactoryAwareOrderSourceProvider(beanFactory, instancesToBeanNames)); instancesToBeanNames.keySet().stream().sorted(comparator).forEach((runner) -> callRunner(runner, args)); }