文章目录
SpringBoot启动类源码分析
1.启动类代码:
package com.example.rfos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // 1. 启动类的组合注解,实现Spring中的Bean的自动装配
public class RfosApplication {
//主函数
public static void main(String[] args)s {
// 2. 调用SpringApplication.run启s动应用,RfosApplication.class 启动类 ,args接收命令行传参
SpringApplication.run(RfosApplication.class, args);
}
}
2.@SpringBootApplication注解源码分析
@SpringBootApplication注解主要由4类注解组成,分别为:JDK原生注解(4个)、@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan。
//1.位于主动装配的包中
package org.springframework.boot.autoconfigure;
@Target({ElementType.TYPE}) //当前注解的使用范围
@Retention(RetentionPolicy.RUNTIME) //注解的生命周期,运行时生效】
@Documented // 声明在生成 doc 文档时是否带着注解
@Inherited //声明是否子类会显示父类的注解,声明的此注解使用了Inherited元注解,表示此注解用在类上时,会被子类所继承
@SpringBootConfiguration // 该类是个配置类功能等同于xml配置文件,实现配置文件的功能
@EnableAutoConfiguration // 本质是@Import,自动导入功能。借助该注解的帮助,将所有符合自动配置条件的 bean 定义加载到 IOC 容器中。@EnableAutoConfiguration会根据类路径中的 jar 依赖为项目进行自动配置
/*@ComponentScan 自动扫描并加载符合条件的组件(如@Component )或者 bean 定义, 最终将这些 bean 定义加载到 IOC 容器中. 也可以通过 basePackages 等属性来细粒度的定制 @ComponentScan 自动扫描的范围, 如果不指定, 则默认扫描 @ComponentScan 所在类的 package 及子包进行扫描。*/
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class<?>[] exclude() default {};
@AliasFor(
annotation = EnableAutoConfiguration.class
)
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "nameGenerator"
)
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
3.@SpringBootApplication的自动装配原理
这个META-INF/spring.factories是自动装配的核心文件
3.1 简述:
使用Spring Boot时,我们只需引入对应的Starters,Spring Boot启动时便会自动加载相关依赖,配置相应的初始化参数,在sprinBoot启动时由@SpringBootApplication注解会自动去maven中读取每个starter中的spring.factories文件,该文件里配置了所有需要被创建spring容器中的bean,并且进行自动配置把bean注入SpringContext**中,这便是Spring Boot的自动配置功能。
3.2详细流程(三个重点注解):
@SpringBootConfiguration 首先表明该启动类是一个配置类;
@ComponentScan 扫描启动类所在的包以及子包下所有标记为Bean的组件并注册到IOC容器中
@EnableAutoConfiguration 实现自动装配的核心注解
3.3 @EnableAutoConfiguration源码分析
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
//用来覆盖开启/关闭自动配置的功能
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
//exclude()和excludeName()可以排除指定的配置
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
a.1 @Import({AutoConfigurationImportSelector.class}) 导入自动配置的选择器,用于导入自动配置的Bean
selectImports()方法为主要实现逻辑:
a. 获取META-INF/spring.factories中EnableAutoConfiguration所对应的Configuration类列表
b. 由@EnableAutoConfiguration注解中的exclude/excludeName参数筛选一遍
c. 再由私有内部类ConfigurationClassFilter筛选一遍,即不满足@Conditional的配置类
主要方法;
-
isEnabled() 判断是否开启了自动配置
-
selectImports()方法 基本包含了组件自动装配的所有处理逻辑
-
getAutoConfigurationEntry() 该方法的作用就是要返回需要注册到IoC容器中的对象对应的类型的全类路径名称的字符串数组
-
getAttributes () 获取自动配置类属性键值对
-
getCandidateConfigurations()获取候选类名集合 ,获取需要自动配置类
-
removeDuplicates () 去重
-
getExclusions() 排除需要排除的配置类–exclude&excludeName&getExcludeAutoConfigurationsProperty
-
getConfigurationClassFilter() 通过过滤器盘判断是否引相关组件,如果有则进行相关配置
-
fireAutoConfigurationImportEvents() 根据spring.factories文件中的AutoConfigurationImportListener事件监听器发布并处理监听事件
-
AutoConfigurationEntry() 返回最终需要托管的类
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
//----省略部分代码----
/*
1. isEnabled() 判断是否开启了自动配置
*/
protected boolean isEnabled(AnnotationMetadata metadata) {
return this.getClass() == AutoConfigurationImportSelector.class ? (Boolean)this.getEnvironment().getProperty("spring.boot.enableautoconfiguration", Boolean.class, true) : true;
}
/*
2. selectImports()方法 基本包含了组件自动装配的所有处理逻辑
AnnotationMetadata 是用来访问指定类上的注解
*/
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 如果未开启自动装配,就返回空数组
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
// 返回需要注册到IoC容器中的对象对应的类型的全类路径名称的字符串数组
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
/*
3. getAutoConfigurationEntry() 该方法的作用就是要返回需要注册到IoC容器中的对象对应的类型的全类路径名称的字符串数组
*/
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
//未开启就返回空数组
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
//获取标注类的元信息
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//加载需要自动装配的候选类名集合
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
//去重
configurations = this.removeDuplicates(configurations);
//排除需要排除的配置类
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 通过过滤器盘判断是否引相关组件,如果有则进行相关配置
configurations = this.getConfigurationClassFilter().filter(configurations);
//派发事件-根据spring.factories文件中的AutoConfigurationImportListener事件监听器发布并处理监听事件
this.fireAutoConfigurationImportEvents(configurations, exclusions);
// 返回最终需要托管的类
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
/*
4. getAttributes () 获取属性键值对
*/
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
String name = this.getAnnotationClass().getName();
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
Assert.notNull(attributes, () -> {
return "No auto-configuration attributes found. Is " + metadata.getClassName() + " annotated with " + ClassUtils.getShortName(name) + "?";
});
return attributes;
}
/*
5.getCandidateConfigurations()获取候选类名集合
而变量configurations 获取的就是自动加载的META-INF/spring.factories中的名为“org.springframework.boot.autoconfigure.EnableAutoConfiguration”的属性值,这里面就是目前spring boot的所有自动配置类。
*/
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
/*
6.removeDuplicates () 去重
*/
protected final <T> List<T> removeDuplicates(List<T> list) {
return new ArrayList(new LinkedHashSet(list));
}
/*
7. getExclusions() 排除需要排除的配置类--exclude&excludeName&getExcludeAutoConfigurationsProperty
*/
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
Set<String> excluded = new LinkedHashSet();
excluded.addAll(this.asList(attributes, "exclude"));
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
excluded.addAll(this.getExcludeAutoConfigurationsProperty());
return excluded;
}
/*
8. getConfigurationClassFilter() 通过过滤器盘判断是否引相关组件,如果有则进行相关配置
*/
private AutoConfigurationImportSelector.ConfigurationClassFilter getConfigurationClassFilter() {
if (this.configurationClassFilter == null) {
List<AutoConfigurationImportFilter> filters = this.getAutoConfigurationImportFilters();
Iterator var2 = filters.iterator();
while(var2.hasNext()) {
AutoConfigurationImportFilter filter = (AutoConfigurationImportFilter)var2.next();
this.invokeAwareMethods(filter);
}
this.configurationClassFilter = new AutoConfigurationImportSelector.ConfigurationClassFilter(this.beanClassLoader, filters);
}
return this.configurationClassFilter;
}
/*
9.fireAutoConfigurationImportEvents() 根据spring.factories文件中的AutoConfigurationImportListener事件监听器发布并处理监听事件
*/
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
List<AutoConfigurationImportListener> listeners = this.getAutoConfigurationImportListeners();
if (!listeners.isEmpty()) {
AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
Iterator var5 = listeners.iterator();
while(var5.hasNext()) {
AutoConfigurationImportListener listener = (AutoConfigurationImportListener)var5.next();
this.invokeAwareMethods(listener);
listener.onAutoConfigurationImportEvent(event);
}
}
}
/**
10. AutoConfigurationEntry() 返回最终需要托管的类
*/
AutoConfigurationEntry(Collection<String> configurations, Collection<String> exclusions) {
this.configurations = new ArrayList(configurations);
this.exclusions = new HashSet(exclusions);
}
//----省略部分源码----
}
a.2 @AutoConfigurationPackage-负责保存标注相关注解的类的所在包路径
表示对于标注该注解的类的包,应当使用AutoConfigurationPackages注册,@AutoConfigurationPackage其实它是一个@Import。@import是什么?@import就是给容器中导入一个组件,这个组件叫什么呢?叫AutoConfigurationPackages.Registrar的组件
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
Registrar.class
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
/**
egisterBeanDefinitions()方法将对应注解所在的包自动配置到容器中,方法具体如下:
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
由于AutoConfigurationPackage注解标注在主类上,得到了主类的包名然后把这个包名最终封装(toArray(new String[0]))到我们的一个数组里面,然后给我们注册(register())进去,相当于我们这个Registrar就是把某一个包下的所有组件批量注册进容器
*/
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}
//是获取需要导入到容器中的包名
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
}
}
3.4 @ComponentScan源码分析
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
//注解是用于声明其它类型注解的元注解,来表示这个声明的注解是可重复的
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
//要扫描的包及其子包, 若要类型安全(避免写错包), 可以使用 basePackageClasses
@AliasFor("basePackages")
String[] value() default {};
//要扫描的包及其子包
@AliasFor("value")
String[] basePackages() default {};
//basePackages 的替代. 可考虑在每个 basePackage 中创建一个特殊的标记类或接口, 用于给这个属性引用
Class<?>[] basePackageClasses() default {};
//自定义bean名称生成器
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
//主要负责对Scope作用域注解的解析
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
//需要扫描包中的那些资源,默认是:**/*.class,即会扫描指定包中所有的class文件
String resourcePattern() default "**/*.class";
//对扫描的类是否启用默认过滤器,默认为true
boolean useDefaultFilters() default true;
//过滤器:用来配置被扫描出来的那些类会被作为组件注册到容器中
ComponentScan.Filter[] includeFilters() default {};
//过滤器,和includeFilters作用刚好相反,用来对扫描的类进行排除的,被排除的类不会被注册到容器中
ComponentScan.Filter[] excludeFilters() default {};
//是否延迟加载-所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。
boolean lazyInit() default f过来前期alse;
// 这个注解可以同时使用多个。
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Filter {
FilterType type() default FilterType.ANNOTATION;
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
}
4.启动类入口主函数-SpringApplication.run(RfosApplication.class, args)-源码分析
首先,Spring Boot项目创建完成会默认生成一个名为 Application 的入口类,我们是通过该类的main方法启动Spring Boot项目的。在main方法中,通过SpringApplication的静态方法,即run方法进行SpringApplication类的实例化操作*,然后再针对实例化对象调用另外一个run方法来完成整个项目的初始化和启动。
SpringApplication调用的run方法的大致流程,如下图:
4.1 调用SpringApplication.run启动springboot应用
public static void main(String[] args) {
SpringApplication.run(RfosApplication.class, args);
}
4.2 使用静态方法启动
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
//创建springapplication对象,调用函数run(args)
return (new SpringApplication(primarySources)).run(args);
}
4.3 run方法启动SpringApplication最核心的逻辑
public ConfigurableApplicationContext run(String... args) {
//用来记录当前Spring Boot启动耗时
StopWatch stopWatch = new StopWatch();
//记录了启动开始时间
stopWatch.start();
//它是任何spring上下文的接口, 所以可以接收任何ApplicationContext实现
ConfigurableApplicationContext context = null;
//SpringBootExceptionReporter的作用就是对启动过程的异常进行分析、报告
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
//1. 开启了Headless模式:
this.configureHeadlessProperty();
//去spring.factroies中读取了SpringApplicationRunListener 的组件, 就是用来发布事件或者运行监听器
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//发布1.ApplicationStartingEvent事件,在运行开始时发送
listeners.starting();
//
Collection exceptionReporters;
try {
// 根据命令行参数 实例化一个ApplicationArguments
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 预初始化环境: 读取环境变量,读取配置文件信息(基于监听器)
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
忽略beaninfo的bean
this.configureIgnoreBeanInfo(environment);
// 打印Banner 横幅
Banner printedBanner = this.printBanner(environment);
// 根据webApplicationType创建Spring上下文
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//预初始化spring上下文
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 加载spring ioc 容器 **相当重要 由于是使用AnnotationConfigServletWebServerApplicationContext 启动的sring容器所以springboot对它做了扩展:
// 加载自动配置类:invokeBeanFactoryPostProcessors , 创建servlet容器onRefresh
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
// 1.将java.awt.headless设置为true,表示运行在服务器器端,在没有显示器器和鼠标键盘的模式下工作,模拟输入输出设备功能。
private void configureHeadlessProperty() {
//将java.awt.headless设置为true,表示运行在服务器器端,在没有显示器器和鼠标键盘的模式下工作,模拟输入输出设备功能。
System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));
}
//2. 去spring.factroies中读取了SpringApplicationRunListener 的组件, 就是用来发布事件或者运行监听器
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
// 3.获取相关的监听器实例
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = this.getClassLoader();
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
//对监听器实例排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
//4. 查找并设置配置文件信息
//SpringApplication:
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
//根据应用类型,创建应用环境:如得到系统的参数、JVM及Servlet等参数,等
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
//将 defaultProperties、commandLine及active-prifiles 属性加载到环境中
//commandLine 在 args 中配置
//其它参数可在如下4个路径中配置:servletConfigInitParams、servletContextInitParams、systemProperties、systemEnvironment
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
//1.1 将 spirng.config 配置文件加载到环境中
listeners.environmentPrepared((ConfigurableEnvironment)environment);
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
//加一个ConfigurationPropertySources
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
根据应用类型,创建应用环境:如得到系统的参数、JVM及Servlet等参数,等
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
} else {
switch(this.webApplicationType) {
case SERVLET:
return new StandardServletEnvironment();
case REACTIVE:
return new StandardReactiveWebEnvironment();
default:
return new StandardEnvironment();
}
}
}
//将 defaultProperties、commandLine及active-prifiles 属性加载到环境中
//commandLine 在 args 中配置
//其它参数可在如下4个路径中配置:servletConfigInitParams、servletContextInitParams、systemProperties、systemEnvironment
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService)conversionService);
}
this.configurePropertySources(environment, args);
this.configureProfiles(environment, args);
}
//
private boolean addConversionService;
//这里的getSharedInstance方法其实就是为了获取并返回ApplicationConversionService的sharedInstance属性,由于这个属性是静态的,所以它只会被初始化一次(也就是单例的)
public static ConversionService getSharedInstance() {
ApplicationConversionService sharedInstance = ApplicationConversionService.sharedInstance;
if (sharedInstance == null) {
Class var1 = ApplicationConversionService.class;
synchronized(ApplicationConversionService.class) {
sharedInstance = ApplicationConversionService.sharedInstance;
if (sharedInstance == null) {
sharedInstance = new ApplicationConversionService();
ApplicationConversionService.sharedInstance = sharedInstance;
}
}
}
// 5.打印Banner图标
private Banner printBanner(ConfigurableEnvironment environment) {
if (this.bannerMode == Mode.OFF) {
return null;
} else {
ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader((ClassLoader)null);
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter((ResourceLoader)resourceLoader, this.banner);
return this.bannerMode == Mode.LOG ? bannerPrinter.print(environment, this.mainApplicationClass, logger) : bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
}
//7.根据webApplicationType创建Spring上下文
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch(this.webApplicationType) {
case SERVLET:
contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
break;
case REACTIVE:
contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
break;
default:
contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
}
} catch (ClassNotFoundException var3) {
throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
}
}
//通过BeanUtils.instantiateClass构造对象,必须要求是具有无参构造函数
return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
// 8.作用是读取spring.factories文件key=ApplicationContextInitializer对应的value并实例化
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = this.getClassLoader();
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
//通过反射构造实例
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList(names.size());
//遍历实例
Iterator var7 = names.iterator();
while(var7.hasNext()) {
String name = (String)var7.next();
try {
//这个工具方法和Class.forName方法作用类似,但是他可以初始化数组和带 ;的Class对象
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
//是否子类和父类关系
Assert.isAssignable(type, instanceClass);
//通过类对象创建构造器
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
//通过 BeanUtils.instantiateClass实例化对象
T instance = BeanUtils.instantiateClass(constructor, args);
//添加实例
instances.add(instance);
} catch (Throwable var12) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);
}
}
/* 9. 1. 准备容器prepareContext()
统一ApplicationContext和Application使用的environment
ApplicationContext的后置处理
执行Initializers
DelegatingApplicationContextInitializer
*/
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
//配置环境
context.setEnvironment(environment);
//后置处理ApplicationContext
this.postProcessApplicationContext(context);
//应用上下文初始化。即系统初始化器的调用
this.applyInitializers(context);
//监听上下文初始化
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
//后置处理ApplicationContext
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", 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(ApplicationConversionService.getSharedInstance());
}
}
// //监听上下文初始化
protected void applyInitializers(ConfigurableApplicationContext context) {
Iterator var2 = this.getInitializers().iterator();
while(var2.hasNext()) {
ApplicationContextInitializer initializer = (ApplicationContextInitializer)var2.next();
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
//10.refresh方法主要是刷新应用程序上下文,这里主要涉及到准备刷新上下文,调用上下文注册为bean的工厂处理器,初始化上下文的消息源,初始化特定上下文子类中的其他特殊bean,检查监听器bean并注册,最后发布相应的事件并销毁已经创建的单例及重置active标志,整体的注解我都直接加在源码中了
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
} catch (AccessControlException var3) {
}
}
this.refresh((ApplicationContext)context);
}
//11.当前方法的代码是空的,可以做一些自定义的后置处理操作
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
}
//12.当应用程序启动时,我们可以让Grails记录一些额外的信息。 类似于应用程序的进程ID(PID)以及应用程序在哪台计算机上启动。 以及启动应用程序所需的时间。 GrailsApp类具有属性logStartupInfo ,默认情况下为true 。 如果属性为true,则在Application类的记录器的INFO和DEBUG级别记录一些额外的行
private boolean logStartupInfo;
oid refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
} catch (AccessControlException var3) {
}
}
this.refresh((ApplicationContext)context);
}
//11.当前方法的代码是空的,可以做一些自定义的后置处理操作
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
}
//12.当应用程序启动时,我们可以让Grails记录一些额外的信息。 类似于应用程序的进程ID(PID)以及应用程序在哪台计算机上启动。 以及启动应用程序所需的时间。 GrailsApp类具有属性logStartupInfo ,默认情况下为true 。 如果属性为true,则在Application类的记录器的INFO和DEBUG级别记录一些额外的行
private boolean logStartupInfo;