版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.13</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
0. 启动类
@SpringBootApplication
public class App {
public static void main(String[] args) {
// SpringApplication.run(App.class, args);
SpringApplication springApplication = new SpringApplication(App.class);
springApplication.setDefaultProperties(Map.of("name","trump")); // set default properties
ConfigurableApplicationContext applicationContext = springApplication.run(args);
applicationContext.registerShutdownHook();
}
}
1. new SpringApplication(App.class)
public class SpringApplication {
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//设置resourceLoader,此时为null
this.resourceLoader = resourceLoader; //主类, App.class
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//REACTIVE,NONE,默认为SERVLET
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//1.1 getSpringFactoriesInstances
//1.2
this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
//a.若在多个文件中:SpringFactoriesLoader.loadFactories()
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//b. 通过反射,构造instance
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
//c. 排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
}
1.1 SpringFactoriesLoader
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
return result;
}
//a.加载所有的 "META-INF/spring.factories"
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
//b.转换为properties
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
//c. 读取properties中的每一行, key为factoryTypeName,value 为具体的实现类名称数组
String factoryTypeName = ((String) entry.getKey()).trim();
String[] factoryImplementationNames =StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
for (String factoryImplementationName : factoryImplementationNames) {
result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>()).add(factoryImplementationName.trim());
}
}
}
//d. distinct()
result.replaceAll((factoryType, implementations) -> implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
cache.put(classLoader, result);
return result;
}
}
spring.factories demo
1.2 关键类
1.2.1 BootstrapRegistryInitializer
接口定义
//package org.springframework.boot;
@FunctionalInterface
public interface BootstrapRegistryInitializer {
void initialize(BootstrapRegistry registry);
}
1.2.2 ApplicationContextInitializer
接口定义
//package org.springframework.context;
@FunctionalInterface
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C applicationContext);
}
spring.factories
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
1.2.3 ApplicationListener
接口定义
//package org.springframework.context;
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
static <T> ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer) {
return event -> consumer.accept(event.getPayload());
}
}
spring.factories
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
2.SpringApplication. run()
public class SpringApplication {
private Set<Class<?>> primarySources; //App.class
private Class<?> mainApplicationClass;
private ResourceLoader resourceLoader;
private WebApplicationType webApplicationType;
private List<ApplicationContextInitializer<?>> initializers;
private List<ApplicationListener<?>> listeners;
private List<BootstrapRegistryInitializer> bootstrapRegistryInitializers;
//DefaultApplicationContextFactory
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
//DefaultApplicationStartup
private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
//2.1 创建DefaultBootstrapContext, for-each bootstrapRegistryInitializers,执行.initialize() -- 略
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();//设置 System.setProperty::"java.awt.headless"
//getSpringFactoriesInstances("SpringApplicationRunListener"), 并构造SpringApplicationRunListeners
SpringApplicationRunListeners listeners = getRunListeners(args);
//2.2 SpringApplicationRunListeners && SpringApplicationRunListener
listeners.starting(bootstrapContext, this.mainApplicationClass);
//2.3 @see:SimpleCommandLineArgsParser --- 略
//获取commandline中的以"--"开头的参数,并以“=”分割,转换为 CommandLineArgs
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//2.4
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
//打印banner-info:
Banner printedBanner = printBanner(environment);
//2.5
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
//2.6
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//2.7
refreshContext(context);
//2.8
afterRefresh(context, applicationArguments);
//2.9 listeners.started()
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
//2.10
callRunners(context, applicationArguments);
//2.11 listeners.ready()
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
return context;
}
}
2.1 createBootstrapContext() --略
2.2 SpringApplicationRunListeners
2.2.1 SpringApplicationRunListeners
class SpringApplicationRunListeners {
private final Log log;
private final List<SpringApplicationRunListener> listeners;
private final ApplicationStartup applicationStartup;
SpringApplicationRunListeners(Log log, List<SpringApplicationRunListener> listeners,
ApplicationStartup applicationStartup) {
this.log = log;
this.listeners = List.copyOf(listeners);
this.applicationStartup = applicationStartup;
}
//略....
//
}
2.2.2 SpringApplicationRunListener
定义ConfigurableApplicationContext 各个生命周期的函数。
方法被调用的顺序如接口内方法定义的顺序
public interface SpringApplicationRunListener {
default void starting(ConfigurableBootstrapContext bootstrapContext) {}
default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,ConfigurableEnvironment environment) {}
default void contextPrepared(ConfigurableApplicationContext context) {}
default void contextLoaded(ConfigurableApplicationContext context) {}
default void started(ConfigurableApplicationContext context, Duration timeTaken) {
started(context);
}
@Deprecated
default void started(ConfigurableApplicationContext context) {}
default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
running(context);
}
@Deprecated
default void running(ConfigurableApplicationContext context) {}
default void failed(ConfigurableApplicationContext context, Throwable exception) {}
}
2.2.3 SpringApplicationRunListener 与 ApplicationListener 之间的关系
2.2.3.1 spring.factories:SpringApplicationRunListener默认实现
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
2.2.3.2 EventPublishingRunListener
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
//获取所有的 ApplicationListener
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
this.initialMulticaster
.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
//.......
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context, timeTaken));
AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
}
}
2.2.4 listeners.starting() — 略
2.3 ApplicationArguments – 略
读取args[]
中,以--key=value
形式的参数,构造DefaultApplicationArguments.
2.4 prepareEnvironment()
2.5 createApplicationContext()
protected ConfigurableApplicationContext createApplicationContext() {
//applicationContextFactory : DefaultApplicationContextFactory
//webApplicationType: WebApplicationType.SERVLET
// 返回: AnnotationConfigServletWebServerApplicationContext
return this.applicationContextFactory.create(this.webApplicationType);
}
DefaultApplicationContextFactory.create()
class DefaultApplicationContextFactory implements ApplicationContextFactory {
//1.
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
//2
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,AnnotationConfigApplicationContext::new);
}
//2
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
//3. load spring.factories 加载org.springframework.boot.ApplicationContextFactory 配置的实现类
for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,getClass().getClassLoader())) {
T result = action.apply(candidate, webApplicationType);
if (result != null) {
return result;
}
}
return (defaultResult != null) ? defaultResult.get() : null;
}
}
spring.factories
org.springframework.boot.ApplicationContextFactory=\
org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext.Factory,\
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory
2.6 prepareContext()
public class SpringApplication {
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);//设置environment
postProcessApplicationContext(context); //略
//1. for-each ApplicationContextInitializer 执行 initializer.initialize(context) --略
applyInitializers(context);
listeners.contextPrepared(context);
bootstrapContext.close(context);
//获取environment中"spring.profiles.active"配置的值,并log
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
beanFactory.registerSingleton("springBootBanner", printedBanner);
//allowCircularReferences , allowBeanDefinitionOverriding
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
// Load the sources
Set<Object> sources = getAllSources();
//2.load(context)
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
protected void load(ApplicationContext context, Object[] sources) {
//2.1 new BeanDefinitionLoader(registry, sources)
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
loader.setBeanNameGenerator(this.beanNameGenerator);
loader.setResourceLoader(this.resourceLoader);
loader.setEnvironment(this.environment);
//2.2 BeanDefinitionLoader.load()
loader.load();
}
}
2.6.1 BeanDefinitionLoader.load()
class BeanDefinitionLoader {
/**
* SpringProperties用来加载"spring.properties"文件的配置信息
*/
private static final boolean XML_ENABLED = !SpringProperties.getFlag("spring.xml.ignore");
//2.1
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
this.sources = sources;
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null);
this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); //App.class
}
//2.2
void load() {
for (Object source : this.sources) {
// load(Class source) -> this.annotatedReader.register(source) --> AnnotatedBeanDefinitionReader.register
load(source);
}
}
}
2.6.2 AnnotatedBeanDefinitionReader.register()
public class AnnotatedBeanDefinitionReader {
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); //App.class
//1. ConditionEvaluator.shouldSkip #####
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//略
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//最终 将main().getClass()即App.class 注册到Spring容器。
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
2.6.2.1 ConditionEvaluator.shouldSkip()
详情见 https://blog.youkuaiyun.com/it_freshman/article/details/134014949
2.7 refreshContext()
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
//1.SpringApplicationShutdownHook
shutdownHook.registerApplicationContext(context);
}
refresh(context);
}
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();
}
2.7.1 registerShutdownHook.registerApplicationContext(context)
class SpringApplicationShutdownHook implements Runnable {
private final Handlers handlers = new Handlers();
private final Set<ConfigurableApplicationContext> contexts = new LinkedHashSet<>();
private final Set<ConfigurableApplicationContext> closedContexts = Collections.newSetFromMap(new WeakHashMap<>());
private final ApplicationContextClosedListener contextCloseListener = new ApplicationContextClosedListener();
void registerApplicationContext(ConfigurableApplicationContext context) {
//1.
addRuntimeShutdownHookIfNecessary();
synchronized (SpringApplicationShutdownHook.class) {
assertNotInProgress();
//99. applicationContext 注册ApplicationContextClosedListener
context.addApplicationListener(this.contextCloseListener);
this.contexts.add(context);
}
}
//1.
private void addRuntimeShutdownHookIfNecessary() {
if (this.shutdownHookAdded.compareAndSet(false, true)) {
//2
addRuntimeShutdownHook();
}
}
//2
void addRuntimeShutdownHook() {
//3. 当进程关闭时,触发thread.start() ->this.run()
Runtime.getRuntime().addShutdownHook(new Thread(this, "SpringApplicationShutdownHook"));
}
//3
@Override
public void run() {
Set<ConfigurableApplicationContext> contexts;
Set<ConfigurableApplicationContext> closedContexts;
Set<Runnable> actions;
synchronized (SpringApplicationShutdownHook.class) {
this.inProgress = true;
contexts = new LinkedHashSet<>(this.contexts);
closedContexts = new LinkedHashSet<>(this.closedContexts);
actions = new LinkedHashSet<>(this.handlers.getActions());
}
//4. 执行close方法
contexts.forEach(this::closeAndWait);
closedContexts.forEach(this::closeAndWait);
//5
actions.forEach(Runnable::run);
}
private void closeAndWait(ConfigurableApplicationContext context) {
if (!context.isActive()) {
return;
}
//call applicationContext.close()
context.close();
//等待容器关闭后,方可返回...
int waited = 0;
while (context.isActive()) {
if (waited > TIMEOUT) {
throw new TimeoutException();
}
Thread.sleep(SLEEP);
waited += SLEEP;
}
}
}
//99
private class ApplicationContextClosedListener implements ApplicationListener<ContextClosedEvent> {
//当ContextClosedEvent 事件发生时,触发此方法
@Override
public void onApplicationEvent(ContextClosedEvent event) {
synchronized (SpringApplicationShutdownHook.class) {
//修改SpringApplicationShutdownHook.contexts,closedContexts 的值
ApplicationContext applicationContext = event.getApplicationContext();
SpringApplicationShutdownHook.this.contexts.remove(applicationContext);
SpringApplicationShutdownHook.this.closedContexts
.add((ConfigurableApplicationContext) applicationContext);
}
}
}
2.7.2 AnnotationConfigServletWebServerApplicationContext.refresh()
2.8 afterRefresh() – 略
默认为空实现,由子类实现。
2.9 listeners.started()—略
2.10 callRunners()
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
两者都是在afterRefresh()
后被调用,区别是方法的入参不同。
2.10.1ApplicationRunner
@FunctionalInterface
public interface ApplicationRunner {
/**
* Callback used to run the bean.
* @param args incoming application arguments
*/
void run(ApplicationArguments args) throws Exception;
}
2.10.2 CommandLineRunner
@FunctionalInterface
public interface CommandLineRunner {
/**
* Callback used to run the bean.
* @param args incoming main method arguments
* @throws Exception on error
*/
void run(String... args) throws Exception;
}