前言
本文是作者写关于Spring源码的第一篇文章,作者水平有限,所有的源码文章仅限用作个人学习记录。文中如有错误欢迎各位留言指正。
run
java
public ConfigurableApplicationContext run(String... args) {
// 为了计时用的,老版本和新版本不一样
long startTime = System.nanoTime();
// 初始化一个引导器的上下文,这是属于Spring Boot的上下文。后边还有一个Spring的上下文。apach好喜欢context这个东西,证明写框架这个context是真的好用。
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
// 这是Spring的上下文,在这里定义,在下面进行的初始化
ConfigurableApplicationContext context = null;
// 配置一个系统属性
configureHeadlessProperty();
// 获取配置文件的监听器 重点 也是扩展点,凡是读取配置文件的地方都是扩展点,因为配置在配置文件中的initializer、listener都会在某个阶段被调用
SpringApplicationRunListeners listeners = getRunListeners(args);
// 调用监听器发送启动事件,这里可以通过自定义监听器消费这个事件,处理自己的逻辑
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 解析命令行参数 将其封装成一个ApplicationArguments,这个类的变量name被设置成commandLineArgs字符串,变量source是解析args封装的CommandLineArgs对象。
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 {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
prepareEnvironment
java
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
// 创建一个配置的环境变量
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 给环境变量中添加args参数资源
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 给环境变量中sources取出来封装成PropertySourcer然后又保存到sources中。
ConfigurationPropertySources.attach(environment);
// 发送环境预处理事件
listeners.environmentPrepared(bootstrapContext, environment);
// 将defaultProperties属性移动到sources的最后去
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;
}
getOrCreateEnvironment
创建配置的环境变量。
java
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
switch (this.webApplicationType) {
case SERVLET:
return new ApplicationServletEnvironment();
case REACTIVE:
return new ApplicationReactiveWebEnvironment();
default:
return new ApplicationEnvironment();
}
}
默认是SERVLET。创建的是ApplicationServletEnvironment
类型实例。
configureEnvironment
java
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
// 默认为true
if (this.addConversionService) {
// 给配置环境对象中添加类型转换器Conversion。构建这个ApplicationConversionService的构造函数中给自己添加了类型转换器和格式化器
environment.setConversionService(new ApplicationConversionService());
}
// 将环境中添加命args参数到source中
configurePropertySources(environment, args);
// 这个方法中没有具体的实现。子类可以继承SpringApplication重写这个方法
configureProfiles(environment, args);
}
ApplicationConversionService
在它的重载的构造方法中调用了configure(this)
方法,这个方法的this就是ApplicationConversionService自己。它也是FormatterRegistry的子类。 总的来说就是给这个类添加了类型转换器和格式化器。
java
public static void configure(FormatterRegistry registry) {
// 给ApplicationConversionService实例中添加默认的类型转换器
DefaultConversionService.addDefaultConverters(registry);
// 添加默认的格式化器
DefaultFormattingConversionService.addDefaultFormatters(registry);
addApplicationFormatters(registry);
addApplicationConverters(registry);
}
addDefaultConverters
DefaultConversionService.addDefaultConverters方法。
ApplicationConversionService也是converterRegistry的子类。
java
public static void addDefaultConverters(ConverterRegistry converterRegistry) {
// 和scalar相关
addScalarConverters(converterRegistry);
// 添加默认的转换器 集合、数组、对象之间的转换
addCollectionConverters(converterRegistry);
// 添加一些转换器
converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new StringToTimeZoneConverter());
converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());
converterRegistry.addConverter(new ObjectToObjectConverter());
converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new FallbackObjectToStringConverter());
converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
}
addCollectionConverters
java
public static void addCollectionConverters(ConverterRegistry converterRegistry) {
ConversionService conversionService = (ConversionService) converterRegistry;
// 数组转集合转换器
converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
// 集合转数组转换器
converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));
// 数组转数组转换器
converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
// 集合转集合转换器
converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
// Map转Map转换器
converterRegistry.addConverter(new MapToMapConverter(conversionService));
// 数组转String类型转换器
converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
// 字符串转数组类型转换器
converterRegistry.addConverter(new StringToArrayConverter(conversionService));
// 数组转对象类型转换器
converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
// 对象转数组类型转换器
converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));
// 集合转String类型转换器
converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
// String转集合类型转换器
converterRegistry.addConverter(new StringToCollectionConverter(conversionService));
// 集合转对象类型转换器
converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
// 对象转集合类型转换器
converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));
// 流转换器
converterRegistry.addConverter(new StreamConverter(conversionService));
}
addDefaultFormatters
DefaultFormattingConversionService.addDefaultFormatters(registry)。
java
public static void addDefaultFormatters(FormatterRegistry formatterRegistry) {
// Default handling of number values
// @NumberFormat注解标注一个字段时,JDBC在读取或写入该字段的值时,会使用NumberFormatAnnotationFormatterFactory创建的格式化器来对值进行格式化处理
formatterRegistry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
// Default handling of monetary values
if (jsr354Present) {
formatterRegistry.addFormatter(new CurrencyUnitFormatter());
formatterRegistry.addFormatter(new MonetaryAmountFormatter());
formatterRegistry.addFormatterForFieldAnnotation(new Jsr354NumberFormatAnnotationFormatterFactory());
}
// Default handling of date-time values
// just handling JSR-310 specific date and time types
// 添加java8出来的日期类型的格式化,跟进去发现是添加了一些类型转换器convertor
new DateTimeFormatterRegistrar().registerFormatters(formatterRegistry);
if (jodaTimePresent) {
// handles Joda-specific types as well as Date, Calendar, Long
new org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar().registerFormatters(formatterRegistry);
}
else {
// regular DateFormat-based Date, Calendar, Long converters
// 之前的日期格式化器
new DateFormatterRegistrar().registerFormatters(formatterRegistry);
}
}
configurePropertySources
给environment中的sources赋值。
java
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
// 获取environment中的sources
MutablePropertySources sources = environment.getPropertySources();
// 如果我们给SpringApplication的defaultProperties赋值了这里会进行解析然后保存找到sources中
if (!CollectionUtils.isEmpty(this.defaultProperties)) {
DefaultPropertiesPropertySource.addOrMerge(this.defaultProperties, sources);
}
// 将命令行参数添加到sources中
if (this.addCommandLineProperties && args.length > 0) {
String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
if (sources.contains(name)) {
PropertySource<?> source = sources.get(name);
CompositePropertySource composite = new CompositePropertySource(name);
composite.addPropertySource(
new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
composite.addPropertySource(source);
sources.replace(name, composite);
}
else {
sources.addFirst(new SimpleCommandLinePropertySource(args));
}
}
}
OK 今天先到这里吧。
See you next time :)