springboot Properties load order source code analysis

About properties:

In the framework of the spring properties is an important part of the Environment object,

springboot has these various ways injection (highest to lowest priority):

1, the command line
java -jar ***.jar --spring.profiles.active=test &
2, java system parameters
System.getProperties()
3. The operating system environment variables.
环境变量。。不解释
4. From the java: to give comp / env in JNDI properties.
不懂是啥,埋坑。
5. RandomValuePropertySource generated by "random. *" Attribute.
springboot中随机端口功能类似的东西吧。
File attributes (spring.config.location parameter) than 6. Application of Jar files
java -jar myproject.jar spring.config.location=classpath:/default.properties
7. Application Jar file inside the file attributes
8. By @PropertySource
@PropertySource("classpath:sys.properties")
@Configuration
public class JavaDoopConfig { } 
9. By default attribute "SpringApplication.setDefaultProperties" declaration.

Source code analysis

1.SpringApplication.run initialization method prepareEnvironment

private ConfigurableEnvironment prepareEnvironment(
            SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments) {
        // 创建Environment对象 ConfigurableEnvironment environment = getOrCreateEnvironment(); //注入commonLine配置源,并提高有限级到最高。 configureEnvironment(environment, applicationArguments.getSourceArgs()); //事件监听,估计跟动态加载有关,太高端不分析了。 listeners.environmentPrepared(environment); bindToSpringApplication(environment); //自定义环境对象,这个也太高端,分析不了。 if (!this.isCustomEnvironment) { environment = new EnvironmentConverter(getClassLoader()) .convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); } //深入jar包了。 ConfigurationPropertySources.attach(environment); return environment; } 
1.1 getOrCreateEnvironment () Analytical Method: initializing StandardServletEnvironment object.
/**
* 根据不同springboot类型创建对应的Environment对象
**/
private ConfigurableEnvironment getOrCreateEnvironment() { if (this.environment != null) { return this.environment; } switch (this.webApplicationType) { case SERVLET: return new StandardServletEnvironment(); case REACTIVE: return new StandardReactiveWebEnvironment(); default: return new StandardEnvironment(); } } /** * 初始化StandardServletEnvironments时,默认添加几种propertySources。 **/ @Override protected void customizePropertySources(MutablePropertySources propertySources) { //servlet上下文中的属性源 propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME)); //servlet配置文件中的属性源 propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)); //Jndi中配置的属性源 if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) { propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME)); } //调用父类方法 super.customizePropertySources(propertySources); } /** * 调用StandardEnvironment对象初始化,系统参数 **/ @Override protected void customizePropertySources(MutablePropertySources propertySources) { //设置java参数属性源 propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties())); //环境变量属性源 propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment())); } 

The above code is invoked addLast method, the lowest priority.
Therefore, the priority order:
. 1, the servlet context
2, servlet configuration file
3, Jndi properties of the source
4, java source parameter attributes.
5, the environment variable properties of the source.

1.2: configureEnvironment Analytical Method:
protected void configureEnvironment(ConfigurableEnvironment environment,String[] args) { //不懂 if (this.addConversionService) { ConversionService conversionService = ApplicationConversionService .getSharedInstance(); environment.setConversionService( (ConfigurableConversionService) conversionService); } //配置加入命令参数配置源 configurePropertySources(environment, args); configureProfiles(environment, args); } protected void configurePropertySources(ConfigurableEnvironment environment,String[] args) { MutablePropertySources sources = environment.getPropertySources(); if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) { sources.addLast( new MapPropertySource("defaultProperties", this.defaultProperties)); } 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)); } } } 

The above code is invoked addFirst method, the highest priority.
Therefore, the priority order:
. 1, CommOnline attribute
2, servlet context
3, servlet configuration file
4, Jndi properties of the source
5, java source parameter attributes.
6, the environment variable properties of the source.

1.3: Event Listener analysis (mmp, look at the source code can not step province, the devil knows what happened inside)
发布ApplicationEnvironmentPreparedEvent事件被ConfigFileApplicationListener监听到。

/**
* 监听到事件后,处理方法
**/
private void onApplicationEnvironmentPreparedEvent( ApplicationEnvironmentPreparedEvent event) { //从spring.factories下获取所有的EnvironmentPostProcessor // EnvironmentPostProcessor为springboot动态管理自定义配置源的接口 //默认3个(json转换啊,系统参数重载啊,vopc云服务相关的) /** * 还有就是ConfigFileApplicationListener 自身也实现可该接口 * 加载springboot相关配置源到容器中。 **/ List<EnvironmentPostProcessor> postProcessors = loadPostProcessors(); postProcessors.add(this); AnnotationAwareOrderComparator.sort(postProcessors); for (EnvironmentPostProcessor postProcessor : postProcessors) { postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication()); } } /** * RandomValuePropertySource 加入优先级 * 很重要,后面慢慢研究,今天只关注配置源 **/ public static void addToEnvironment(ConfigurableEnvironment environment) { //加载环境变量优先级后面 environment.getPropertySources().addAfter( StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new RandomValuePropertySource(RANDOM_PROPERTY_SOURCE_NAME)); logger.trace("RandomValuePropertySource add to Environment"); } /** * 然后调用了springboot读取配置的核心方法。 **/ public void load() { this.profiles = new LinkedList<>(); this.processedProfiles = new LinkedList<>(); this.activatedProfiles = false; this.loaded = new LinkedHashMap<>(); initializeProfiles(); while (!this.profiles.isEmpty()) { Profile profile = this.profiles.poll(); if (profile != null && !profile.isDefaultProfile()) { addProfileToEnvironment(profile.getName()); } load(profile, this::getPositiveProfileFilter, addToLoaded(MutablePropertySources::addLast, false)); this.processedProfiles.add(profile); } resetEnvironmentProfiles(this.processedProfiles); load(null, this::getNegativeProfileFilter, addToLoaded(MutablePropertySources::addFirst, true)); //上面各种嵌套逻辑,加载好配置后 addLoadedPropertySources(); } /** * 依次加载配置文件到最后。 **/ private void addLoadedPropertySource(MutablePropertySources destination, String lastAdded, PropertySource<?> source) { if (lastAdded == null) { if (destination.contains(DEFAULT_PROPERTIES)) { destination.addBefore(DEFAULT_PROPERTIES, source); } else { destination.addLast(source); } } else { destination.addAfter(lastAdded, source); } } 

Therefore, the priority order after the change:
. 1, CommOnline attribute
2, servlet context
3, servlet configuration file
4, Jndi properties of the source
5, java source parameter attributes.
6, the environment variable properties of the source.
7, random properties of the source.
8, springboot source configuration (application-dev.yml precedence application.yml)

 




Guess you like

Origin www.cnblogs.com/exmyth/p/11349575.html