|
|
|
|
@ -18,12 +18,15 @@ package org.springframework.boot;
@@ -18,12 +18,15 @@ package org.springframework.boot;
|
|
|
|
|
|
|
|
|
|
import java.lang.StackWalker.StackFrame; |
|
|
|
|
import java.lang.management.ManagementFactory; |
|
|
|
|
import java.lang.reflect.Method; |
|
|
|
|
import java.time.Duration; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.Collection; |
|
|
|
|
import java.util.Collections; |
|
|
|
|
import java.util.Comparator; |
|
|
|
|
import java.util.HashMap; |
|
|
|
|
import java.util.IdentityHashMap; |
|
|
|
|
import java.util.LinkedHashSet; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
@ -41,14 +44,17 @@ import org.crac.management.CRaCMXBean;
@@ -41,14 +44,17 @@ import org.crac.management.CRaCMXBean;
|
|
|
|
|
|
|
|
|
|
import org.springframework.aot.AotDetector; |
|
|
|
|
import org.springframework.beans.BeansException; |
|
|
|
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException; |
|
|
|
|
import org.springframework.beans.factory.config.BeanDefinition; |
|
|
|
|
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; |
|
|
|
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory; |
|
|
|
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; |
|
|
|
|
import org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader; |
|
|
|
|
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory; |
|
|
|
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry; |
|
|
|
|
import org.springframework.beans.factory.support.BeanNameGenerator; |
|
|
|
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory; |
|
|
|
|
import org.springframework.beans.factory.support.RootBeanDefinition; |
|
|
|
|
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; |
|
|
|
|
import org.springframework.boot.Banner.Mode; |
|
|
|
|
import org.springframework.boot.context.properties.bind.Bindable; |
|
|
|
|
@ -74,6 +80,8 @@ import org.springframework.context.event.ContextRefreshedEvent;
@@ -74,6 +80,8 @@ import org.springframework.context.event.ContextRefreshedEvent;
|
|
|
|
|
import org.springframework.context.support.AbstractApplicationContext; |
|
|
|
|
import org.springframework.context.support.GenericApplicationContext; |
|
|
|
|
import org.springframework.core.GenericTypeResolver; |
|
|
|
|
import org.springframework.core.OrderComparator; |
|
|
|
|
import org.springframework.core.OrderComparator.OrderSourceProvider; |
|
|
|
|
import org.springframework.core.Ordered; |
|
|
|
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator; |
|
|
|
|
import org.springframework.core.annotation.Order; |
|
|
|
|
@ -762,35 +770,42 @@ public class SpringApplication {
@@ -762,35 +770,42 @@ public class SpringApplication {
|
|
|
|
|
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
private void callRunners(ConfigurableApplicationContext context, ApplicationArguments args) { |
|
|
|
|
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); |
|
|
|
|
String[] beanNames = beanFactory.getBeanNamesForType(Runner.class); |
|
|
|
|
Map<Runner, String> instancesToBeanNames = new IdentityHashMap<>(); |
|
|
|
|
for (String beanName : beanNames) { |
|
|
|
|
instancesToBeanNames.put(beanFactory.getBean(beanName, Runner.class), beanName); |
|
|
|
|
} |
|
|
|
|
Comparator<Object> comparator = getOrderComparator(beanFactory) |
|
|
|
|
.withSourceProvider(new FactoryAwareOrderSourceProvider(beanFactory, instancesToBeanNames)); |
|
|
|
|
instancesToBeanNames.keySet().stream().sorted(comparator).forEach((runner) -> callRunner(runner, args)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void callRunner(ApplicationRunner runner, ApplicationArguments args) { |
|
|
|
|
try { |
|
|
|
|
(runner).run(args); |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) { |
|
|
|
|
throw new IllegalStateException("Failed to execute ApplicationRunner", ex); |
|
|
|
|
} |
|
|
|
|
private OrderComparator getOrderComparator(ConfigurableListableBeanFactory beanFactory) { |
|
|
|
|
Comparator<?> dependencyComparator = (beanFactory instanceof DefaultListableBeanFactory defaultListableBeanFactory) |
|
|
|
|
? defaultListableBeanFactory.getDependencyComparator() : null; |
|
|
|
|
return (dependencyComparator instanceof OrderComparator orderComparator) ? orderComparator |
|
|
|
|
: AnnotationAwareOrderComparator.INSTANCE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void callRunner(CommandLineRunner runner, ApplicationArguments args) { |
|
|
|
|
try { |
|
|
|
|
(runner).run(args.getSourceArgs()); |
|
|
|
|
private void callRunner(Runner runner, ApplicationArguments args) { |
|
|
|
|
if (runner instanceof ApplicationRunner) { |
|
|
|
|
callRunner(ApplicationRunner.class, runner, (applicationRunner) -> applicationRunner.run(args)); |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) { |
|
|
|
|
throw new IllegalStateException("Failed to execute CommandLineRunner", ex); |
|
|
|
|
if (runner instanceof CommandLineRunner) { |
|
|
|
|
callRunner(CommandLineRunner.class, runner, |
|
|
|
|
(commandLineRunner) -> commandLineRunner.run(args.getSourceArgs())); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
private <R extends Runner> void callRunner(Class<R> type, Runner runner, ThrowingConsumer<R> call) { |
|
|
|
|
call.throwing( |
|
|
|
|
(message, ex) -> new IllegalStateException("Failed to execute " + ClassUtils.getShortName(type), ex)) |
|
|
|
|
.accept((R) runner); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception, |
|
|
|
|
SpringApplicationRunListeners listeners) { |
|
|
|
|
try { |
|
|
|
|
@ -1636,8 +1651,8 @@ public class SpringApplication {
@@ -1636,8 +1651,8 @@ public class SpringApplication {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Starts a non-daemon thread to keep the JVM alive on {@link ContextRefreshedEvent}. |
|
|
|
|
* Stops the thread on {@link ContextClosedEvent}. |
|
|
|
|
* <<<<<<< HEAD Starts a non-daemon thread to keep the JVM alive on |
|
|
|
|
* {@link ContextRefreshedEvent}. Stops the thread on {@link ContextClosedEvent}. |
|
|
|
|
*/ |
|
|
|
|
private static final class KeepAlive implements ApplicationListener<ApplicationContextEvent> { |
|
|
|
|
|
|
|
|
|
@ -1774,4 +1789,41 @@ public class SpringApplication {
@@ -1774,4 +1789,41 @@ public class SpringApplication {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* {@link OrderSourceProvider} used to obtain factory method and target type order |
|
|
|
|
* sources. Based on internal {@link DefaultListableBeanFactory} code. |
|
|
|
|
*/ |
|
|
|
|
private class FactoryAwareOrderSourceProvider implements OrderSourceProvider { |
|
|
|
|
|
|
|
|
|
private final ConfigurableBeanFactory beanFactory; |
|
|
|
|
|
|
|
|
|
private final Map<?, String> instancesToBeanNames; |
|
|
|
|
|
|
|
|
|
FactoryAwareOrderSourceProvider(ConfigurableBeanFactory beanFactory, Map<?, String> instancesToBeanNames) { |
|
|
|
|
this.beanFactory = beanFactory; |
|
|
|
|
this.instancesToBeanNames = instancesToBeanNames; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Object getOrderSource(Object obj) { |
|
|
|
|
String beanName = this.instancesToBeanNames.get(obj); |
|
|
|
|
return (beanName != null) ? getOrderSource(beanName, obj.getClass()) : null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Object getOrderSource(String beanName, Class<?> instanceType) { |
|
|
|
|
try { |
|
|
|
|
RootBeanDefinition beanDefinition = (RootBeanDefinition) this.beanFactory |
|
|
|
|
.getMergedBeanDefinition(beanName); |
|
|
|
|
Method factoryMethod = beanDefinition.getResolvedFactoryMethod(); |
|
|
|
|
Class<?> targetType = beanDefinition.getTargetType(); |
|
|
|
|
targetType = (targetType != instanceType) ? targetType : null; |
|
|
|
|
return Stream.of(factoryMethod, targetType).filter(Objects::nonNull).toArray(); |
|
|
|
|
} |
|
|
|
|
catch (NoSuchBeanDefinitionException ex) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|