回顾之前的代码,主要做了两件事
- 将配置的运行监听器实例化
- 创建启动事件实例,并推送给适配的监听器处理(logback读取配置文件、完成预初始化)
继续
创建应用参数集合实例
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
— DefaultApplicationArguments start
org.springframework.boot.DefaultApplicationArguments
private final Source source;
private final String[] args;
public DefaultApplicationArguments(String... args) {
Assert.notNull(args, "Args must not be null");
this.source = new Source(args);
this.args = args;
}
—— Source start
org.springframework.boot.ApplicationArguments$Source
Source(String[] args) {
super(args);
}
查看父级构造方法
——— SimpleCommandLinePropertySource start
org.springframework.core.env.SimpleCommandLinePropertySource
public SimpleCommandLinePropertySource(String... args) {
super(new SimpleCommandLineArgsParser().parse(args));
}
重点看解析方法
———— parse start
org.springframework.core.env.SimpleCommandLineArgsParser
public CommandLineArgs parse(String... args) {
CommandLineArgs commandLineArgs = new CommandLineArgs();
for (String arg : args) {
if (arg.startsWith("--")) {
String optionText = arg.substring(2);
String optionName;
String optionValue = null;
int indexOfEqualsSign = optionText.indexOf('=');
if (indexOfEqualsSign > -1) {
optionName = optionText.substring(0, indexOfEqualsSign);
optionValue = optionText.substring(indexOfEqualsSign + 1);
}
else {
optionName = optionText;
}
if (optionName.isEmpty()) {
throw new IllegalArgumentException("Invalid argument syntax: " + arg);
}
commandLineArgs.addOptionArg(optionName, optionValue);
}
else {
commandLineArgs.addNonOptionArg(arg);
}
}
return commandLineArgs;
}
遍历参数集合
若参数是否以 - - 开头,根据 = 拆分参数名与值,通过addOptionArg
方法添加
commandLineArgs.addOptionArg(optionName, optionValue);
————— addOptionArg start
org.springframework.core.env.CommandLineArgs
private final Map<String, List<String>> optionArgs = new HashMap<>();
public void addOptionArg(String optionName, @Nullable String optionValue) {
if (!this.optionArgs.containsKey(optionName)) {
this.optionArgs.put(optionName, new ArrayList<>());
}
if (optionValue != null) {
this.optionArgs.get(optionName).add(optionValue);
}
}
————— addOptionArg end
否则通过addNonOptionArg
方法添加
commandLineArgs.addNonOptionArg(arg);
————— addNonOptionArg start
org.springframework.core.env.CommandLineArgs
private final List<String> nonOptionArgs = new ArrayList<>();
public void addNonOptionArg(String value) {
this.nonOptionArgs.add(value);
}
————— addNonOptionArg end
———— parse end
接着看父级构造方法
———— CommandLinePropertySource start
org.springframework.core.env.CommandLinePropertySource
public static final String COMMAND_LINE_PROPERTY_SOURCE_NAME = "commandLineArgs";
public CommandLinePropertySource(T source) {
super(COMMAND_LINE_PROPERTY_SOURCE_NAME, source);
}
接着看父级构造方法
————— EnumerablePropertySource start
org.springframework.util.ObjectUtils.EnumerablePropertySource
public EnumerablePropertySource(String name, T source) {
super(name, source);
}
接着看父级构造方法
—————— PropertySource start
org.springframework.core.env.PropertySource
protected final String name;
protected final T source;
public PropertySource(String name, T source) {
Assert.hasText(name, "Property source name must contain at least one character");
Assert.notNull(source, "Property source must not be null");
this.name = name;
this.source = source;
}
—————— PropertySource end
————— EnumerablePropertySource end
———— CommandLinePropertySource end
——— SimpleCommandLinePropertySource end
—— Source end
— DefaultApplicationArguments end
准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
— prepareEnvironment start
org.springframework.boot.SpringApplication
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;
}
获取或创建环境实例
ConfigurableEnvironment environment = getOrCreateEnvironment();
—— getOrCreateEnvironment start
org.springframework.boot.SpringApplication
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();
}
}
由于此前未创建环境实例,environment
为null
根据webApplicationType
创建并返回org.springframework.boot.ApplicationEnvironment
实例
查看父类构造方法
——— AbstractEnvironment start
org.springframework.core.env.AbstractEnvironment
private final MutablePropertySources propertySources;
private final ConfigurablePropertyResolver propertyResolver;
public AbstractEnvironment() {
this(new MutablePropertySources());
}
protected AbstractEnvironment(MutablePropertySources propertySources) {
this.propertySources = propertySources;
this.propertyResolver = createPropertyResolver(propertySources);
customizePropertySources(propertySources);
}
创建属性分解器
this.propertyResolver = createPropertyResolver(propertySources);
———— createPropertyResolver start
org.springframework.boot.ApplicationEnvironment
@Override
protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {
return ConfigurationPropertySources.createPropertyResolver(propertySources);
}
————— createPropertyResolver start
org.springframework.boot.context.properties.source.ConfigurationPropertySources
public static ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {
return new ConfigurationPropertySourcesPropertyResolver(propertySources);
}
创建配置属性资源属性分解器
—————— ConfigurationPropertySourcesPropertyResolver start
org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver
private final MutablePropertySources propertySources;
private final DefaultResolver defaultResolver;
ConfigurationPropertySourcesPropertyResolver(MutablePropertySources propertySources) {
this.propertySources = propertySources;
this.defaultResolver = new DefaultResolver(propertySources);
}
创建默认的分解器
——————— DefaultResolver start
org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver$DefaultResolver
DefaultResolver(PropertySources propertySources) {
super(propertySources);
}
查看父类构造方法
———————— PropertySourcesPropertyResolver start
org.springframework.core.env.PropertySourcesPropertyResolver
@Nullable
private final PropertySources propertySources;
public PropertySourcesPropertyResolver(@Nullable PropertySources propertySources) {
this.propertySources = propertySources;
}
———————— PropertySourcesPropertyResolver end
——————— DefaultResolver end
—————— ConfigurationPropertySourcesPropertyResolver end
————— createPropertyResolver end
———— createPropertyResolver end
定制属性资源
———— customizePropertySources start
org.springframework.core.env.StandardEnvironment
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(
new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
获取系统属性并添加
propertySources.addLast(
new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
————— getSystemProperties start
org.springframework.core.env.AbstractEnvironment
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public Map<String, Object> getSystemProperties() {
try {
return (Map) System.getProperties();
}
catch (AccessControlException ex) {
return (Map) new ReadOnlySystemAttributesMap() {
@Override
@Nullable
protected String getSystemAttribute(String attributeName) {
try {
return System.getProperty(attributeName);
}
catch (AccessControlException ex) {
if (logger.isInfoEnabled()) {
logger.info("Caught AccessControlException when accessing system property '" +
attributeName + "'; its value will be returned [null]. Reason: " + ex.getMessage());
}
return null;
}
}
};
}
}
————— getSystemProperties end
获取系统环境并添加
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
————— getSystemEnvironment start
org.springframework.core.env.AbstractEnvironment
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public Map<String, Object> getSystemEnvironment() {
if (suppressGetenvAccess()) {
return Collections.emptyMap();
}
try {
return (Map) System.getenv();
}
catch (AccessControlException ex) {
return (Map) new ReadOnlySystemAttributesMap() {
@Override
@Nullable
protected String getSystemAttribute(String attributeName) {
try {
return System.getenv(attributeName);
}
catch (AccessControlException ex) {
if (logger.isInfoEnabled()) {
logger.info("Caught AccessControlException when accessing system environment variable '" +
attributeName + "'; its value will be returned [null]. Reason: " + ex.getMessage());
}
return null;
}
}
};
}
}
————— getSystemEnvironment end
———— customizePropertySources end
——— AbstractEnvironment end
—— getOrCreateEnvironment end
配置环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
注意此处getSourceArgs
方法获取的为原始参数集合(String[]
),并非处理后的实例(org.springframework.core.env.CommandLineArgs
)
—— configureEnvironment start
org.springframework.boot.SpringApplication
private boolean addConversionService = true;
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
environment.setConversionService(new ApplicationConversionService());
}
configurePropertySources(environment, args);
configureProfiles(environment, args);
}
设置转换服务
environment.setConversionService(new ApplicationConversionService());
创建转换服务实例
——— ApplicationConversionService start
org.springframework.boot.convert.ApplicationConversionService
private final boolean unmodifiable;
public ApplicationConversionService() {
this(null);
}
public ApplicationConversionService(StringValueResolver embeddedValueResolver) {
this(embeddedValueResolver, false);
}
private ApplicationConversionService(StringValueResolver embeddedValueResolver, boolean unmodifiable) {
if (embeddedValueResolver != null) {
setEmbeddedValueResolver(embeddedValueResolver);
}
configure(this);
this.unmodifiable = unmodifiable;
}
设置内嵌值分解器
setEmbeddedValueResolver(embeddedValueResolver);
———— setEmbeddedValueResolver start
org.springframework.format.support.FormattingConversionService
@Nullable
private StringValueResolver embeddedValueResolver;
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.embeddedValueResolver = resolver;
}
此处分解器为null,无需设置
———— setEmbeddedValueResolver end
配置自身实例
configure(this);
———— configure start
org.springframework.boot.convert.ApplicationConversionService
public static void configure(FormatterRegistry registry) {
DefaultConversionService.addDefaultConverters(registry);
DefaultFormattingConversionService.addDefaultFormatters(registry);
addApplicationFormatters(registry);
addApplicationConverters(registry);
}
添加默认的转换器
DefaultConversionService.addDefaultConverters(registry);
————— addDefaultConverters start
org.springframework.core.convert.support.DefaultConversionService
public static void addDefaultConverters(ConverterRegistry converterRegistry) {
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));
}
添加标量转换器
—————— addScalarConverters start
org.springframework.core.convert.support.DefaultConversionService
private static void addScalarConverters(ConverterRegistry converterRegistry) {
converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());
converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToCharacterConverter());
converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new NumberToCharacterConverter());
converterRegistry.addConverterFactory(new CharacterToNumberFactory());
converterRegistry.addConverter(new StringToBooleanConverter());
converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
converterRegistry.addConverter(new EnumToStringConverter((ConversionService) converterRegistry));
converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());
converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService) converterRegistry));
converterRegistry.addConverter(new StringToLocaleConverter());
converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToCharsetConverter());
converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToCurrencyConverter());
converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToPropertiesConverter());
converterRegistry.addConverter(new PropertiesToStringConverter());
converterRegistry.addConverter(new StringToUUIDConverter());
converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
}
—————— addScalarConverters end
添加集合转换器
—————— addCollectionConverters start
org.springframework.core.convert.support.DefaultConversionService
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));
converterRegistry.addConverter(new MapToMapConverter(conversionService));
converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
converterRegistry.addConverter(new StringToArrayConverter(conversionService));
converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));
converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
converterRegistry.addConverter(new StringToCollectionConverter(conversionService));
converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));
converterRegistry.addConverter(new StreamConverter(conversionService));
}
—————— addCollectionConverters end
————— addDefaultConverters end
添加默认的格式器
DefaultFormattingConversionService.addDefaultFormatters(registry);
————— addDefaultFormatters start
org.springframework.format.support.DefaultFormattingConversionService
public static void addDefaultFormatters(FormatterRegistry formatterRegistry) {
// Default handling of number values
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
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);
}
}
主要为时间和货币的格式化器、注解工厂等
addFormatterForFieldAnnotation
方法用于添加成员属性的格式化注解
—————— addFormatterForFieldAnnotation start
org.springframework.boot.convert.ApplicationConversionService
@Override
public void addFormatterForFieldAnnotation(
AnnotationFormatterFactory<? extends Annotation> annotationFormatterFactory) {
assertModifiable();
super.addFormatterForFieldAnnotation(annotationFormatterFactory);
}
验证是否可修改
assertModifiable();
——————— assertModifiable start
org.springframework.boot.convert.ApplicationConversionService
private void assertModifiable() {
if (this.unmodifiable) {
throw new UnsupportedOperationException("This ApplicationConversionService cannot be modified");
}
}
——————— assertModifiable end
其他添加方法也均调用assertModifiable
方法验证
调用父类方法
super.addFormatterForFieldAnnotation(annotationFormatterFactory);
——————— addFormatterForFieldAnnotation start
org.springframework.format.support.FormattingConversionService
@Override
public void addFormatterForFieldAnnotation(AnnotationFormatterFactory<? extends Annotation> annotationFormatterFactory) {
Class<? extends Annotation> annotationType = getAnnotationType(annotationFormatterFactory);
if (this.embeddedValueResolver != null && annotationFormatterFactory instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) annotationFormatterFactory).setEmbeddedValueResolver(this.embeddedValueResolver);
}
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
for (Class<?> fieldType : fieldTypes) {
addConverter(new AnnotationPrinterConverter(annotationType, annotationFormatterFactory, fieldType));
addConverter(new AnnotationParserConverter(annotationType, annotationFormatterFactory, fieldType));
}
}
获取注解类型
Class<? extends Annotation> annotationType = getAnnotationType(annotationFormatterFactory);
———————— getAnnotationType start
org.springframework.format.support.FormattingConversionService
@SuppressWarnings("unchecked")
static Class<? extends Annotation> getAnnotationType(AnnotationFormatterFactory<? extends Annotation> factory) {
Class<? extends Annotation> annotationType = (Class<? extends Annotation>)
GenericTypeResolver.resolveTypeArgument(factory.getClass(), AnnotationFormatterFactory.class);
if (annotationType == null) {
throw new IllegalArgumentException("Unable to extract parameterized Annotation type argument from " +
"AnnotationFormatterFactory [" + factory.getClass().getName() +
"]; does the factory parameterize the <A extends Annotation> generic type?");
}
return annotationType;
}
获取类型
Class<? extends Annotation> annotationType = (Class<? extends Annotation>)
GenericTypeResolver.resolveTypeArgument(factory.getClass(), AnnotationFormatterFactory.class);
————————— resolveTypeArgument start
org.springframework.core.GenericTypeResolver
@Nullable
public static Class<?> resolveTypeArgument(Class<?> clazz, Class<?> genericIfc) {
ResolvableType resolvableType = ResolvableType.forClass(clazz).as(genericIfc);
if (!resolvableType.hasGenerics()) {
return null;
}
return getSingleGeneric(resolvableType);
}
获取类型信息
ResolvableType resolvableType = ResolvableType.forClass(clazz).as(genericIfc);
可知此时获取的为工厂实例作为org.springframework.format.AnnotationFormatterFactory
的信息
获取单个泛型
return getSingleGeneric(resolvableType);
—————————— getSingleGeneric start
org.springframework.core.GenericTypeResolver
@Nullable
private static Class<?> getSingleGeneric(ResolvableType resolvableType) {
Assert.isTrue(resolvableType.getGenerics().length == 1,
() -> "Expected 1 type argument on generic interface [" + resolvableType +
"] but found " + resolvableType.getGenerics().length);
return resolvableType.getGeneric().resolve();
}
—————————— getSingleGeneric end
返回工厂作为org.springframework.format.AnnotationFormatterFactory
时的泛型
————————— resolveTypeArgument end
验证后返回
if (annotationType == null) {
throw new IllegalArgumentException("Unable to extract parameterized Annotation type argument from " +
"AnnotationFormatterFactory [" + factory.getClass().getName() +
"]; does the factory parameterize the <A extends Annotation> generic type?");
}
return annotationType;
———————— getAnnotationType end
设置内嵌值分解器
if (this.embeddedValueResolver != null && annotationFormatterFactory instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) annotationFormatterFactory).setEmbeddedValueResolver(this.embeddedValueResolver);
}
由前文可知,embeddedValueResolver
为null
获取成员属性的类型集合
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
此处以org.springframework.format.number.NumberFormatAnnotationFormatterFactory
为例
———————— getFieldTypes start
org.springframework.format.number.NumberFormatAnnotationFormatterFactory
@Override
public Set<Class<?>> getFieldTypes() {
return NumberUtils.STANDARD_NUMBER_TYPES;
}
org.springframework.util.NumberUtils
public static final Set<Class<?>> STANDARD_NUMBER_TYPES;
static {
Set<Class<?>> numberTypes = new HashSet<>(8);
numberTypes.add(Byte.class);
numberTypes.add(Short.class);
numberTypes.add(Integer.class);
numberTypes.add(Long.class);
numberTypes.add(BigInteger.class);
numberTypes.add(Float.class);
numberTypes.add(Double.class);
numberTypes.add(BigDecimal.class);
STANDARD_NUMBER_TYPES = Collections.unmodifiableSet(numberTypes);
}
———————— getFieldTypes end
遍历集合添加打印器和解析器
for (Class<?> fieldType : fieldTypes) {
addConverter(new AnnotationPrinterConverter(annotationType, annotationFormatterFactory, fieldType));
addConverter(new AnnotationParserConverter(annotationType, annotationFormatterFactory, fieldType));
}
创建注解打印器转换器
———————— AnnotationPrinterConverter start
org.springframework.format.support.FormattingConversionService$AnnotationPrinterConverter
private final Class<? extends Annotation> annotationType;
@SuppressWarnings("rawtypes")
private final AnnotationFormatterFactory annotationFormatterFactory;
private final Class<?> fieldType;
public AnnotationPrinterConverter(Class<? extends Annotation> annotationType,
AnnotationFormatterFactory<?> annotationFormatterFactory, Class<?> fieldType) {
this.annotationType = annotationType;
this.annotationFormatterFactory = annotationFormatterFactory;
this.fieldType = fieldType;
}
———————— AnnotationPrinterConverter end
创建注解解析器转换器
———————— AnnotationParserConverter start
org.springframework.format.support.FormattingConversionService$AnnotationParserConverter
private final Class<? extends Annotation> annotationType;
@SuppressWarnings("rawtypes")
private final AnnotationFormatterFactory annotationFormatterFactory;
private final Class<?> fieldType;
public AnnotationParserConverter(Class<? extends Annotation> annotationType,
AnnotationFormatterFactory<?> annotationFormatterFactory, Class<?> fieldType) {
this.annotationType = annotationType;
this.annotationFormatterFactory = annotationFormatterFactory;
this.fieldType = fieldType;
}
———————— AnnotationParserConverter end
addConverter
方法用于添加转换器,与前面的addFormatterForFieldAnnotation
方法类似
———————— addConverter start
org.springframework.boot.convert.ApplicationConversionService
@Override
public void addConverter(GenericConverter converter) {
assertModifiable();
super.addConverter(converter);
}
验证可修改
assertModifiable();
调用父类方法
super.addConverter(converter);
————————— addConverter start
org.springframework.core.convert.support.GenericConversionService
private final Converters converters = new Converters();
@Override
public void addConverter(GenericConverter converter) {
this.converters.add(converter);
invalidateCache();
}
添加转换器
this.converters.add(converter);
—————————— add start
org.springframework.core.convert.support.GenericConversionService$Converters
private final Set<GenericConverter> globalConverters = new CopyOnWriteArraySet<>();
public void add(GenericConverter converter) {
Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();
if (convertibleTypes == null) {
Assert.state(converter instanceof ConditionalConverter,
"Only conditional converters may return null convertible types");
this.globalConverters.add(converter);
}
else {
for (ConvertiblePair convertiblePair : convertibleTypes) {
getMatchableConverters(convertiblePair).add(converter);
}
}
}
获取可转换类型集合
Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();
——————————— getConvertibleTypes start
org.springframework.format.support.FormattingConversionService$AnnotationPrinterConverter
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(this.fieldType, String.class));
}
创建可转换对
new ConvertiblePair(this.fieldType, String.class)
——————————— ConvertiblePair start
org.springframework.core.convert.converter.GenericConverter$ConvertiblePair
private final Class<?> sourceType;
private final Class<?> targetType;
public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
Assert.notNull(sourceType, "Source type must not be null");
Assert.notNull(targetType, "Target type must not be null");
this.sourceType = sourceType;
this.targetType = targetType;
}
——————————— ConvertiblePair end
创建集合并返回
—————————— getConvertibleTypes end
添加转换器
由于上一步获取的类型集合不为空,遍历并加入
for (ConvertiblePair convertiblePair : convertibleTypes) {
getMatchableConverters(convertiblePair).add(converter);
}
获取匹配的转换器集合
——————————— getMatchableConverters start
org.springframework.core.convert.support.GenericConversionService$Converters
private final Map<ConvertiblePair, ConvertersForPair> converters = new ConcurrentHashMap<>(256);
private ConvertersForPair getMatchableConverters(ConvertiblePair convertiblePair) {
return this.converters.computeIfAbsent(convertiblePair, k -> new ConvertersForPair());
}
以convertiblePair
为键,返回或创建实例
——————————— getMatchableConverters end
添加至转换器
——————————— add start
org.springframework.core.convert.support.GenericConversionService$ConvertersForPair
private final Deque<GenericConverter> converters = new ConcurrentLinkedDeque<>();
public void add(GenericConverter converter) {
this.converters.addFirst(converter);
}
——————————— add end
—————————— add end
清理缓存
invalidateCache();
—————————— invalidateCache start
org.springframework.core.convert.support.GenericConversionService
private final Map<ConverterCacheKey, GenericConverter> converterCache = new ConcurrentReferenceHashMap<>(64);
private void invalidateCache() {
this.converterCache.clear();
}
—————————— invalidateCache end
————————— addConverter end
———————— addConverter end
——————— addFormatterForFieldAnnotation end
—————— addFormatterForFieldAnnotation end
————— addDefaultFormatters end
添加应用格式器
addApplicationFormatters(registry);
————— addApplicationFormatters start
org.springframework.boot.convert.ApplicationConversionService
public static void addApplicationFormatters(FormatterRegistry registry) {
registry.addFormatter(new CharArrayFormatter());
registry.addFormatter(new InetAddressFormatter());
registry.addFormatter(new IsoOffsetFormatter());
}
————— addApplicationFormatters end
添加应用转换器
addApplicationConverters(registry);
————— addApplicationConverters start
org.springframework.boot.convert.ApplicationConversionService
public static void addApplicationConverters(ConverterRegistry registry) {
addDelimitedStringConverters(registry);
registry.addConverter(new StringToDurationConverter());
registry.addConverter(new DurationToStringConverter());
registry.addConverter(new NumberToDurationConverter());
registry.addConverter(new DurationToNumberConverter());
registry.addConverter(new StringToPeriodConverter());
registry.addConverter(new PeriodToStringConverter());
registry.addConverter(new NumberToPeriodConverter());
registry.addConverter(new StringToDataSizeConverter());
registry.addConverter(new NumberToDataSizeConverter());
registry.addConverter(new StringToFileConverter());
registry.addConverter(new InputStreamSourceToByteArrayConverter());
registry.addConverterFactory(new LenientStringToEnumConverterFactory());
registry.addConverterFactory(new LenientBooleanToEnumConverterFactory());
if (registry instanceof ConversionService) {
addApplicationConverters(registry, (ConversionService) registry);
}
}
添加分隔字符串转换器
addDelimitedStringConverters(registry);
—————— addDelimitedStringConverters start
org.springframework.boot.convert.ApplicationConversionService
public static void addDelimitedStringConverters(ConverterRegistry registry) {
ConversionService service = (ConversionService) registry;
registry.addConverter(new ArrayToDelimitedStringConverter(service));
registry.addConverter(new CollectionToDelimitedStringConverter(service));
registry.addConverter(new DelimitedStringToArrayConverter(service));
registry.addConverter(new DelimitedStringToCollectionConverter(service));
}
用于字符串和集合/数组间转换
—————— addDelimitedStringConverters end
添加最后的转换器
addApplicationConverters(registry, (ConversionService) registry);
—————— addApplicationConverters start
org.springframework.boot.convert.ApplicationConversionService
private static void addApplicationConverters(ConverterRegistry registry, ConversionService conversionService) {
registry.addConverter(new CharSequenceToObjectConverter(conversionService));
}
org.springframework.boot.convert.CharSequenceToObjectConverter
其本质为代理,使用代理实例的转换器
—————— addApplicationConverters end
这里代理了实例本身,可使用已注册的转换器
————— addApplicationConverters end
———— configure end
设置是否可修改
this.unmodifiable = unmodifiable;
unmodifiable
为false,表示当前实例可修改,后面会看到
——— ApplicationConversionService end
org.springframework.boot.convert.ApplicationConversionService
创建完成
——— setConversionService start
org.springframework.core.env.AbstractEnvironment
@Override
public void setConversionService(ConfigurableConversionService conversionService) {
this.propertyResolver.setConversionService(conversionService);
}
———— setConversionService start
org.springframework.core.env.AbstractPropertyResolver
@Nullable
private volatile ConfigurableConversionService conversionService;
@Override
public void setConversionService(ConfigurableConversionService conversionService) {
Assert.notNull(conversionService, "ConversionService must not be null");
this.conversionService = conversionService;
}
———— setConversionService end
——— setConversionService end
配置属性资源
configurePropertySources(environment, args);
——— configurePropertySources start
org.springframework.boot.SpringApplication
private boolean addCommandLineProperties = true;
private Map<String, Object> defaultProperties;
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
MutablePropertySources sources = environment.getPropertySources();
if (!CollectionUtils.isEmpty(this.defaultProperties)) {
DefaultPropertiesPropertySource.addOrMerge(this.defaultProperties, 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));
}
}
}
获取前面创建的属性资源
MutablePropertySources sources = environment.getPropertySources();
包括系统属性和系统环境
添加默认的属性
if (!CollectionUtils.isEmpty(this.defaultProperties)) {
DefaultPropertiesPropertySource.addOrMerge(this.defaultProperties, sources);
}
默认属性为null
添加命令行属性资源
当存在命令行参数时
if (this.addCommandLineProperties && args.length > 0)
获取命令行属性资源名称
String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
即commandLineArgs
若资已包含,则以springApplicationCommandLineArgs之名创建新的命令行属性资源,与原本的命令行属性资源整合
PropertySource<?> source = sources.get(name);
CompositePropertySource composite = new CompositePropertySource(name);
composite.addPropertySource(
new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
composite.addPropertySource(source);
sources.replace(name, composite);
不包含则直接添加
sources.addFirst(new SimpleCommandLinePropertySource(args));
——— configurePropertySources end
配置概述
configureProfiles(environment, args);
——— configureProfiles start
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
}
此为空方法
——— configureProfiles end
—— configureEnvironment end
将属性资源附加于环境实例
ConfigurationPropertySources.attach(environment);
—— attach start
org.springframework.boot.context.properties.source.ConfigurationPropertySources
public static void attach(Environment environment) {
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
PropertySource<?> attached = getAttached(sources);
if (attached == null || !isUsingSources(attached, sources)) {
attached = new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
new SpringConfigurationPropertySources(sources));
}
sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
sources.addFirst(attached);
}
获取属性资源
MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
——— getPropertySources start
org.springframework.core.env.AbstractEnvironment
@Override
public MutablePropertySources getPropertySources() {
return this.propertySources;
}
propertySources
于上文的构造方法内设置
——— getPropertySources end
获取附加的属性资源
PropertySource<?> attached = getAttached(sources);
——— getAttached start
org.springframework.boot.context.properties.source.ConfigurationPropertySources
private static final String ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties";
static PropertySource<?> getAttached(MutablePropertySources sources) {
return (sources != null) ? sources.get(ATTACHED_PROPERTY_SOURCE_NAME) : null;
}
——— getAttached end
当前attached
为null
判断是否使用资源
isUsingSources(attached, sources)
——— isUsingSources start
org.springframework.boot.context.properties.source.ConfigurationPropertySources
private static boolean isUsingSources(PropertySource<?> attached, MutablePropertySources sources) {
return attached instanceof ConfigurationPropertySourcesPropertySource
&& ((SpringConfigurationPropertySources) attached.getSource()).isUsingSources(sources);
}
判断attached
类后获取其资源实例并转换
———— isUsingSources start
org.springframework.boot.context.properties.source.SpringConfigurationPropertySources
boolean isUsingSources(Iterable<PropertySource<?>> sources) {
return this.sources == sources;
}
———— isUsingSources end
最终比对实例地址是否相同
——— isUsingSources end
创建新的实例
attached = new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
new SpringConfigurationPropertySources(sources));
———— SpringConfigurationPropertySources start
org.springframework.boot.context.properties.source.SpringConfigurationPropertySources
private final Iterable<PropertySource<?>> sources;
SpringConfigurationPropertySources(Iterable<PropertySource<?>> sources) {
Assert.notNull(sources, "Sources must not be null");
this.sources = sources;
}
———— SpringConfigurationPropertySources end
对应上文isUsingSources
方法内对资源实例的强制类转换
———— ConfigurationPropertySourcesPropertySource start
org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource
ConfigurationPropertySourcesPropertySource(String name, Iterable<ConfigurationPropertySource> source) {
super(name, source);
}
查看父类构造方法
————— PropertySource start
org.springframework.core.env.PropertySource
protected final String name;
protected final T source;
public PropertySource(String name, T source) {
Assert.hasText(name, "Property source name must contain at least one character");
Assert.notNull(source, "Property source must not be null");
this.name = name;
this.source = source;
}
————— PropertySource end
———— ConfigurationPropertySourcesPropertySource end
对应上文isUsingSources
方法内对attach
类型判断
从资源实例移除原本的实例
sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
添加至资源实例
sources.addFirst(attached);
—— attach end
监听器的环境准备
listeners.environmentPrepared(bootstrapContext, environment);
—— environmentPrepared start
org.springframework.boot.SpringApplicationRunListeners
void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
doWithListeners("spring.boot.application.environment-prepared",
(listener) -> listener.environmentPrepared(bootstrapContext, environment));
}
类似于之前的启动方法,关注运行监听器的environmentPrepared
方法即可
——— environmentPrepared start
org.springframework.boot.context.event.EventPublishingRunListener
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(
new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
}
创建org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent
事件实例并交由匹配的监听器的onApplicationEvent
方法处理
当前匹配的监听器共6个
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
org.springframework.boot.context.config.AnsiOutputApplicationListener
org.springframework.boot.context.logging.LoggingApplicationListener
org.springframework.boot.autoconfigure.BackgroundPreinitializer
org.springframework.boot.context.config.DelegatingApplicationListener
org.springframework.boot.context.FileEncodingApplicationListener
由于篇幅问题,将监听器的执行放在后文
——— environmentPrepared end
—— environmentPrepared end
— prepareEnvironment end