• 使用 SpringFactoriesLoader 在应用的 classpath 中查找并加载所有可用的 ApplicationListener。

[外链图片转存中…(img-1zXUD30Y-1711155633696)]

[外链图片转存中…(img-Ivmj5ecF-1711155633697)]

复制代码

  • 推断并设置 main 方法的定义类。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_加载

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_加载_02

/**
• Create a new {@link SpringApplication} instance. The application context will load
• beans from the specified primary sources (see {@link SpringApplication class-level}
• documentation for details. The instance can be customized before calling
• {@link #run(String…)}.
• @param resourceLoader the resource loader to use
• @param primarySources the primary bean sources
• @see #run(Class, String[])
• @see #setSources(Set)
*/
@SuppressWarnings({ “unchecked”, “rawtypes” })
public SpringApplication(ResourceLoader resourceLoader, Class<?>… primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, “PrimarySources must not be null”);
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = deduceWebApplicationType();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}

复制代码

  1. SpringApplication 实例初始化完成并且完成设置后,就开始执行 run 方法的逻辑了,方法执行伊始,首先遍历执行所有通过 SpringFactoriesLoader 可以查找到并加载的 SpringApplicationRunListener。 调用它们的 started() 方法,告诉这些 SpringApplicationRunListener,“嘿,SpringBoot 应用要开始执行咯!”。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_spring boot_03

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_加载_04

  1. 创建并配置当前 Spring Boot 应用将要使用的 Environment(包括配置要使用的 PropertySource 以及 Profile )。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_算法_05

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_spring boot_06

  1. 遍历调用所有 SpringApplicationRunListener 的 environmentPrepared() 的方法,告诉他们:“当前 SpringBoot 应用使用的 Environment 准备好了咯!”。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_java_07

  1. 如果 SpringApplication 的 showBanner 属性被设置为 true ,则打印 banner。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_java_08

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_加载_09

  1. 根据用户是否明确设置了 applicationContextClass 类型以及初始化阶段的推断结果,决定该为当前 SpringBoot 应用创建什么类型的 ApplicationContext 并创建完成,然后根据条件决定是否添加 ShutdownHook ,决定是否使用自定义的 BeanNameGenerator,决定是否使用自定义的 ResourceLoader,当然,最重要的,将之前准备好的 Environment 设置给创建好的 ApplicationContext 使用。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_外链_10

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_算法_11

  1. ApplicationContext 创建好之后,SpringApplication 会再次借助 Spring-FactoriesLoader,查找并加载 classpath 中所有可用的 ApplicationContext-Initializer,然后遍历调用这些 ApplicationContextInitializer 的 initialize(applicationContext)方法来对已经创建好的 ApplicationContext 进行进一步的处理。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_加载_12

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_算法_13

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_外链_14

  1. 遍历调用所有 SpringApplicationRunListener 的 contextPrepared() 方法。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_加载_15

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_算法_16

  1. 最核心的一步,将之前通过 @EnableAutoConfiguration 获取的所有配置以及其他形式的 IoC 容器配置加载到已经准备完毕的 ApplicationContext。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_算法_17

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_java_18

  1. 遍历调用所有 SpringApplicationRunListener 的 contextLoaded() 方法。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_spring boot_19

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_算法_20

  1. 调用 ApplicationContext 的 refresh() 方法,完成 IoC 容器可用的最后一道工序。

springboot 集成 mysql sqlserver springboot 集成netty 启动等待问题_算法_21

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 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);
// Invoke factory processors registered as beans in the context.===>从Spring容器中找出BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor接口的实现类并按照一定的规则顺序进行执行。 其中ConfigurationClassPostProcessor这个BeanDefinitionRegistryPostProcessor优先级最高,它会对项目中的@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理)进行解析,解析完成之后把这些bean注册到BeanFactory中。需要注意的是这个时候注册进来的bean还没有实例化。
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 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);
}