springboot源码剖析(三) 环境配置
概念
springboot在启动流程中会把环境配置都加载进应用当中。
实现原理
使用环境配置器用来加载和解析所有配置文件。配置文件会被抽象成PropertySource对象存储。
uml类图
环境配置流程
源码剖析
环境配置
/** SpringApplication.class 环境配置 **/ // 配置入口 public ConfigurableApplicationContext run(String... args) { // ... // 解析命令行参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // ★解析配置文件 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); // ... } // 解析配置文件 private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { // 1.获取环境配置器 ConfigurableEnvironment environment = this.getOrCreateEnvironment(); // ★2.环境配置器配置 this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs()); // 环境配置器配置文件列表加ConfigurationPropertySources类 ConfigurationPropertySources.attach((Environment)environment); // ★3.事件发布器:通知监听者环境准备好了(监听者主要是加配置文件) // 其中ConfigFileApplicationListener加载了yml文件和中间件的配置 listeners.environmentPrepared((ConfigurableEnvironment)environment); // 4.spring类绑定source属性(我的没绑到符合的) this.bindToSpringApplication((ConfigurableEnvironment)environment); // 5.不标准的环境配置器类会被强转成标准类 if (!this.isCustomEnvironment) { environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass()); } // 6.绑定source属性 ConfigurationPropertySources.attach((Environment)environment); return (ConfigurableEnvironment)environment; } // 1.获取环境配置器 private ConfigurableEnvironment getOrCreateEnvironment() { if (this.environment != null) { return this.environment; } else { // 由web应用类型决定,服务器是StandardServletEnvironment类 switch(this.webApplicationType) { case SERVLET: // 服务器为StandardServletEnvironment,构造会初始化资源解析器和读取定制化配置文件 return new StandardServletEnvironment(); case REACTIVE: return new StandardReactiveWebEnvironment(); default: return new StandardEnvironment(); } } } // 2.环境配置器配置 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); }
环境配置器
/** StandardServletEnvironment.class 环境配置器 */ public class StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment { // 定制配置文件加载 protected void customizePropertySources(MutablePropertySources propertySources) { propertySources.addLast(new StubPropertySource("servletConfigInitParams")); propertySources.addLast(new StubPropertySource("servletContextInitParams")); if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) { propertySources.addLast(new JndiPropertySource("jndiProperties")); } super.customizePropertySources(propertySources); } } /** AbstractEnvironment.class 环境配置器基类 */ public abstract class AbstractEnvironment implements ConfigurableEnvironment { public static final String IGNORE_GETENV_PROPERTY_NAME = "spring.getenv.ignore"; public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active"; public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default"; protected static final String RESERVED_DEFAULT_PROFILE_NAME = "default"; protected final Log logger = LogFactory.getLog(this.getClass()); // 动态开发环境 private final Set<String> activeProfiles = new LinkedHashSet(); // 默认开发环境 private final Set<String> defaultProfiles = new LinkedHashSet(this.getReservedDefaultProfiles()); // 配置文件列表 private final MutablePropertySources propertySources = new MutablePropertySources(); // 资源解析器 private final ConfigurablePropertyResolver propertyResolver; // 构造:实例化一个资源解析器,将定制化资源加载到配置文件列表中 public AbstractEnvironment() { this.propertyResolver = new PropertySourcesPropertyResolver(this.propertySources); this.customizePropertySources(this.propertySources); } } /** MutablePropertySources.class 配置文件列表 */ public class MutablePropertySources implements PropertySources { // 配置文件都会被抽象成对象放在这里 private final List<PropertySource<?>> propertySourceList; }