1、初始化
1、获取 initializers
// 加载类路径中所有"META-INF/spring.factories"文件中的所有属性文件,查找键为“org.springframework.context.ApplicationContextInitializer”的类列表,实例化所有ApplicationContextInitializer类
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
2、获取listeners
// 加载类路径中所有"META-INF/spring.factories"文件中的所有属性文件,查找键为“org.springframework.context.ApplicationListener”的类列表,实例化所有ApplicationListener类
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
3、设置 mainApplicationClass
// this.mainApplicationClass = cn.java.springboot.demo.main2.Main
this.mainApplicationClass = deduceMainApplicationClass(); // 检查栈中含有main方法的类
2、执行
1、创建SpringApplicationRunListeners对象(全局环境中,实际只有一个 EventPublishingRunListener,用于管理 SpringApplication.listeners )
1、加载类路径中所有"META-INF/spring.factories"文件中的所有属性文件,查找键为SpringApplicationRunListener的类列表,实例化所有SpringApplicationRunListener类
2、实例化所有 SpringApplicationRunListener,并把 SpringApplication 和 args 作为参数注入
2、触发事件 --- 事件
# 调用SpringApplicationRunListeners对象的starting方法
listeners.starting(); // 迭代调用实现SpringApplicationRunListener接口的listener的starting方法
3、创建《环境》
StandardServletEnvironment
4、打印信息到控制台
5、创建上下文
AnnotationConfigEmbeddedWebApplicationContext
6、创建失败分析器
1、在“META-INF/spring.factories”查找,实现FailureAnalyzer接口的analyzers列表
2、通过 context.getBeanFactory() 获取,给analyzers注入beanFactory
7、预备上下文
1、设置环境 environment 到 context
2、设置 context 属性
1、设置bean名生成器
context.getBeanFactory().registerSingleton(...)
2、设置资源加载器
。。
3、设置类加载器
。。
3、迭代 SpringApplication.initializers 列表,调用 initialize(context) 方法
8、触发事件 --- 事件
listeners.contextPrepared(context);
9、注册对象到 BeanFactory
注册 《参数 》对象到 BeanFactory
注册 printedBanner 对象到 BeanFactory
10、加载资源
1、创建 BeanDefinitionLoader 对象
1、对sources依赖
2、创建《各种文件类型》的解析器
1、注册 Processor,处理 @Configuration、@Autowired 注解等。。!!! ------ 对注解的核心支持
2、设置 BeanDefinitionLoader 的 bean名生成器
3、设置 BeanDefinitionLoader 的 资源加载器
3、设置 BeanDefinitionLoader 的 类加载器
2、调用 BeanDefinitionLoader 加载 bean 定义 !!!! 按《文件类型》加载资源
11、触发事件 --- 事件
listeners.contextLoaded(context);
12、刷新上下文
1、调用context.refresh(); 加载ApplicationContext.xml文件
1、常规的 context.refresh() 功能
1、处理环境相关
2、调用bean的postProcessBeanDefinitionRegistry(...)方法
{
1、处理 cn.java.demo.user.MainApplication 类(因为 @SpringBootApplication 注解内有 @ComponentScan 注解)
{
1、解析 parse(Set<BeanDefinitionHolder> configCandidates) - // 解析 MainApplication 类 --- 创建新的configClass & 无依赖父configClass
{
1、parse(String className, String beanName)
{
processConfigurationClass(ConfigurationClass configClass)
{
1、检查 @Conditional 的条件
2、doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
{
1、处理《内部类》
如果存在,递归到 《processConfigurationClass(ConfigurationClass configClass)》 (即:深度优先)--- 创建新的configClass & 依赖父configClass
2、处理 @PropertySources 注解
即刻导入资源配置,并设置到 environment
3、处理 @ComponentScans 注解 & 检查 @Conditional 的条件
1、立刻扫描含有 @Component、@ManagedBean、@Named 注解的类,并放入 scannedBeanDefinitions
2、迭代扫描出来的 scannedBeanDefinitions
递归到 parse(String className, String beanName) ,处理扫描到的bean --- (即:深度优先)创建新的configClass & 不依赖父configClass
4、《processImports》处理 @Import 注解
1、是 ImportSelector 的子类
1、是 DeferredImportSelector 的子类
添加到 this.deferredImportSelectors 列表
2、不是 DeferredImportSelector 的子类
递归到 《processImports》,执行到
2、是 ImportBeanDefinitionRegistrar 的子类
添加到 configClass.importBeanDefinitionRegistrars
3、其他
递归到 《processConfigurationClass(ConfigurationClass configClass)》,进行解析 --- (即:深度优先)创建新的configClass & 依赖父configClass
5、处理 @ImportResource 注解
添加到 configClass.importedResources
6、处理 带有@Bean注解的方法列表
添加到 configClass.beanMethods
7、读取所有父接口的《带有@Bean注解的方法列表》
添加到 configClass.beanMethods
}
3、注册 configClass 到 configurationClasses ----- 添加 configClass
}
}
2、执行 this.deferredImportSelectors 列表
1、执行 《processImports》 导入处理
}
2、调用 loadBeanDefinitions,执行 Bean 定义加载
{
1、检查 @Conditional 的条件
2、把 configClass 子级的 configClass 注册到 beanFactory --- 会进入第二解析
3、处理 @Bean 方法,configClass.beanMethods,用工厂模式包装,并注册到 beanFactory
1、带有@Bean注解的方法列表
2、所有父接口的《带有@Bean注解的方法列表》
4、处理 @ImportResource 的后续,(即:configClass.importedResources)
执行xml资源导入
5、处理@Import注解且继承ImportBeanDefinitionRegistrar,(即:configClass.importBeanDefinitionRegistrars)
。。
}
}
}
3、调用 bean的postProcessBeanFactory方法
4、注册 BeanPostProcessor
等等。。。
2、上下文容器 tomcat 的获取
3、上下文容器 tomcat 的启动
2、调用context.registerShutdownHook();
13、《刷新》后续处理
1、扫描 context 中实现 ApplicationRunner 接口的 bean 列表
2、扫描 context 中实现 CommandLineRunner 接口的 bean 列表
3、迭代调用的 ApplicationRunner 类型bean的 run 方法
4、迭代调用的 CommandLineRunner 类型bean的 run 方法
14、触发事件 --- 事件
listeners.finished(context, null);