概要
- spring-boot-2.6.4.jar
- org.springframework.boot.SpringApplication
run
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);}
//*******
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
//context 初始化
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
//设置系统参数java.awt.headless为true,允许无其他硬件(键盘、鼠标、显示器)的情况下运行。
configureHeadlessProperty();
//listener 初始化
SpringApplicationRunListeners listeners = getRunListeners(args);
//listener启动运行
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//context初始化
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
//
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
//运行
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
//处理异常
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
//listener 初始化完成
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
//处理异常
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
DefaultBootstrapContext 初始化
- 会调用 bootstrapRegistryInitializers的 initialize 来初始化DefaultBootstrapContext
- bootstrapRegistryInitializers最终是通过 SpringFactoriesLoader 从FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories” 这加载的
- 所以 他把这个初始化DefaultBootstrapContext任务交给了在spring.factories指定的BootstrapRegistryInitializer类处理的
初始化 DefaultBootstrapContext能干什么?//TODO
- 实例管理 存map key是Class, value 是实例引用或 能实例化的工具类
listener管理 ```java
private
Collection getSpringFactoriesInstances(Class type) { return getSpringFactoriesInstances(type, new Class<?>[] {}); } private
Collection getSpringFactoriesInstances(Class type, Class<?>[] parameterTypes, Object… args) { ClassLoader classLoader = getClassLoader(); // Use names and ensure unique to protect against duplicates Set names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
public SpringApplication(ResourceLoader resourceLoader, Class<?>… primarySources) { //… this.bootstrapRegistryInitializers = new ArrayList<>( getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); //… }
private DefaultBootstrapContext createBootstrapContext() { DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext(); this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext)); return bootstrapContext; }
<a name="j7mTo"></a>
### SpringApplicationRunListeners初始化和运行
- 也是通过 SpringFactoriesLoader 从_FACTORIES_RESOURCE_LOCATION _= "META-INF/spring.factories" 这加载的
- spring-boot-xxx.jar里 有一个默认
org.springframework.boot.SpringApplicationRunListener=\<br />org.springframework.boot.context.event.EventPublishingRunListener //TODO <br />�
```java
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
- 执行 SpringApplicationRunListeners 中 applicationStartup 的start,这个applicationStartup是SpringApplication中初始化的用了ApplicationStartup._DEFAULT 即 _DefaultApplicationStartup
- 执行每个 listener的starting方法
- 执行step.tag, 这里的step是 DefaultApplicationStartup start函数返回的 DefaultStartupStep里的实现,你没什么实现的东西
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction,
Consumer<StartupStep> stepAction) {
StartupStep step = this.applicationStartup.start(stepName);
this.listeners.forEach(listenerAction);
if (stepAction != null) {
stepAction.accept(step);
}
step.end();
}
ConfigurableEnvironment 初始化
- ConfigurableEnvironments是管理配置文件的,
- 参考 https://www.cnblogs.com/youzhibing/p/9622441.html
- prepareEnvironment方法到底做了什么
- 加载外部化配置资源到environment,包括命令行参数、servletConfigInitParams、servletContextInitParams、systemProperties、sytemEnvironment、random、application.yml(.yaml/.xml/.properties)等;
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
"Environment prefix cannot be set via properties.");
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = convertEnvironment(environment);
}
ConfigurationPropertySources.attach(environment);
return environment;
}
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
environment.setConversionService(new ApplicationConversionService());
}
configurePropertySources(environment, args); //把命令行的把环境变量定义加进来
configureProfiles(environment, args); // 从配置文件把环境变量定义参数加进来,这个SpringApplication没找到源码实现,应该不同子类里覆盖了
}
ConfigurableApplicationContext 初始化更新
createApplicationContext
- 下面这个applicationContextFactory会根据不同类型取初始化
```java
//…..
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
//………. /// protected ConfigurableApplicationContext createApplicationContext() {try { switch (webApplicationType) { case SERVLET: return new (); case REACTIVE: return new AnnotationConfigReactiveWebServerApplicationContext(); default: return new AnnotationConfigApplicationContext(); } }
}return this.applicationContextFactory.create(this.webApplicationType);
- ApplicationContextFactory 的实现类 AnnotationConfigServletWebServerApplicationContext
- //TODO
�
<a name="ZCKC6"></a>
### prepareContext
- 参考 [https://www.jianshu.com/p/bcdeb14ef710](https://www.jianshu.com/p/bcdeb14ef710)
```java
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
//ApplicationContext的后置处理
postProcessApplicationContext(context);
//依次 ApplicationContextInitializer 列表的内对象的 initialize方法
applyInitializers(context);
listeners.contextPrepared(context);
bootstrapContext.close(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
postProcessApplicationContext
主要是注册设置下面几个东西,从SpringApplication Environment设置到 context 和context的BeanFactory
- beanNameGenerator
- resourceLoader
- addConversionService
protected void postProcessApplicationContext(ConfigurableApplicationContext context) { if (this.beanNameGenerator != null) { context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, this.beanNameGenerator); } if (this.resourceLoader != null) { if (context instanceof GenericApplicationContext) { ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader); } if (context instanceof DefaultResourceLoader) { ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader()); } } if (this.addConversionService) { context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService()); } }applyInitializers
ApplicationContextInitializer 是个接口 //TODO 找些扩展例子
- SpringApplication 的成员initializers 可以通过 setInitializers addInitializers 添加
�
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
listeners.contextPrepared(context);
- SpringApplicationRunListener的contextPrepared没有实现 ,
- 具体的 listenter 从 context获取信息 作一些操作 ```java void contextPrepared(ConfigurableApplicationContext context) { doWithListeners(“spring.boot.application.context-prepared”, (listener) -> listener.contextPrepared(context)); }
<a name="Uqk94"></a>
#### bootstrapContext.close(context); 启动上下文关闭
```java
public void close(ConfigurableApplicationContext applicationContext) {
this.events.multicastEvent(new BootstrapContextClosedEvent(this, applicationContext));
}
Add boot specific singleton beans
- beanFactory.registerSingleton(“springApplicationArguments”, applicationArguments);
- beanFactory.registerSingleton(“springBootBanner”, printedBanner);
- setAllowCircularReferences //TODO 好像和循环依赖有关
- setAllowBeanDefinitionOverriding
addBeanFactoryPostProcessor
- ConfigurableApplicationContext没实现这个,要看context里设置的是
- beanFactoryPostProcessors添加了这个 Processor后内,context的refresh时会按照一定顺序执行这个processer
```java
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); }
///。。。。。。。 @Override public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) { Assert.notNull(postProcessor, “BeanFactoryPostProcessor must not be null”); this.beanFactoryPostProcessors.add(postProcessor); }
<a name="FQMXv"></a>
#### Load the sources
- 注册bean
- 不同源码类型不同load
- 其中一个分支是到 AnnotatedBeanDefinitionReader的 registerBean
```java
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
loader.load();
}
listeners.contextLoaded(context);
- 具体看各自实例的实现
下面是 EventPublishingRunListener里的实现
public void contextLoaded(ConfigurableApplicationContext context) { for (ApplicationListener<?> listener : this.application.getListeners()) { if (listener instanceof ApplicationContextAware) { ((ApplicationContextAware) listener).setApplicationContext(context); } context.addApplicationListener(listener); } this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context)); }获取对应事件的listener去执行event
@Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }怎么获取listener ```java protected Collection
> getApplicationListeners( ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class<?> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Potential new retriever to populate CachedListenerRetriever newRetriever = null; // Quick check for existing entry on ConcurrentHashMap CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey); if (existingRetriever == null) { // Caching a new ListenerRetriever if possible if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { newRetriever = new CachedListenerRetriever(); existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever); if (existingRetriever != null) { newRetriever = null; // no need to populate it in retrieveApplicationListeners } } } if (existingRetriever != null) { Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners(); if (result != null) { return result; } // If result is null, the existing retriever is not fully populated yet by another thread. // Proceed like caching wasn't possible for this current local attempt. } return retrieveApplicationListeners(eventType, sourceType, newRetriever);}
private Collection
List<ApplicationListener<?>> allListeners = new ArrayList<>();
Set<ApplicationListener<?>> filteredListeners = (retriever != null ? new LinkedHashSet<>() : null);
Set<String> filteredListenerBeans = (retriever != null ? new LinkedHashSet<>() : null);
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.defaultRetriever) {
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
}
// Add programmatically registered listeners, including ones coming
// from ApplicationListenerDetector (singleton beans and inner beans).
for (ApplicationListener<?> listener : listeners) {
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
filteredListeners.add(listener);
}
allListeners.add(listener);
}
}
// Add listeners by bean name, potentially overlapping with programmatically
// registered listeners above - but here potentially with additional metadata.
if (!listenerBeans.isEmpty()) {
ConfigurableBeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : listenerBeans) {
try {
if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
if (beanFactory.isSingleton(listenerBeanName)) {
filteredListeners.add(listener);
}
else {
filteredListenerBeans.add(listenerBeanName);
}
}
allListeners.add(listener);
}
}
else {
// Remove non-matching listeners that originally came from
// ApplicationListenerDetector, possibly ruled out by additional
// BeanDefinition metadata (e.g. factory method generics) above.
Object listener = beanFactory.getSingleton(listenerBeanName);
if (retriever != null) {
filteredListeners.remove(listener);
}
allListeners.remove(listener);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
AnnotationAwareOrderComparator.sort(allListeners);
if (retriever != null) {
if (filteredListenerBeans.isEmpty()) {
retriever.applicationListeners = new LinkedHashSet<>(allListeners);
retriever.applicationListenerBeans = filteredListenerBeans;
}
else {
retriever.applicationListeners = filteredListeners;
retriever.applicationListenerBeans = filteredListenerBeans;
}
}
return allListeners;
}
<a name="D3AVp"></a>
### refreshContext,
```java
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
shutdownHook.registerApplicationContext(context);
}
refresh(context);
}
shutdownHook
- context 里塞了 ApplicationContextClosedListener的实例,
- 把这个context 也赛道了自己 的contexts 一个Set
void registerApplicationContext(ConfigurableApplicationContext context) {
addRuntimeShutdownHookIfNecessary();
synchronized (SpringApplicationShutdownHook.class) {
assertNotInProgress();
context.addApplicationListener(this.contextCloseListener);
this.contexts.add(context);
}
}
refresh(context) //重点
默认的 refresh 实现 在AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); beanPostProcess.end(); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); contextRefresh.end(); } } }afterRefresh
�
listeners.started
callRunners
- ApplicationRunner
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); } } }
handleRunFailure
private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception,
SpringApplicationRunListeners listeners) {
try {
try {
handleExitCode(context, exception);
if (listeners != null) {
listeners.failed(context, exception);
}
}
finally {
reportFailure(getExceptionReporters(context), exception);
if (context != null) {
context.close();
shutdownHook.deregisterFailedApplicationContext(context);
}
}
}
catch (Exception ex) {
logger.warn("Unable to close ApplicationContext", ex);
}
ReflectionUtils.rethrowRuntimeException(exception);
}

