The configuration source of the application is usually the remote Config Server server. By default, the local configuration priority is lower than the remote configuration repository. If you want to implement the local application system variables and config files to overwrite the property values in the remote repository, you can set them as follows:
spring:cloud:config:allowOverride: trueoverrideNone: trueoverrideSystemProperties: false
Through the above configuration, the client can achieve higher priority in local configuration and cannot be overwritten. Since the current version of Spring Cloud we are based on is Edgware.RELEASE , the above settings do not work, but use the default values in PropertySourceBootstrapProperties . For specific situations, see issue: https://github.com/spring-cloud/spring-cloud-commons/pull/250. We will talk about the specific source of the bug in the following analysis.
Source code analysis
ConfigServicePropertySourceLocator
Overwriting the remote configuration properties is ultimately related to obtaining the configuration at the start of the client. How to deal with it after obtaining the configuration? Let's take a look at the class diagram of the resource acquisition class ConfigServicePropertySourceLocator in spring cloud config.
ConfigServicePropertySourceLocator is essentially a property resource locator, and its main method is location(Environment environment). First, replace the placeholder in configClientProperties with the application, profile and label of the environment where the application is currently running, and initialize the RestTemplate, then iterate through the labels array until valid configuration information is obtained, and finally retry based on whether it fails quickly. The main process is as follows:
locate(Environment environment) Call the getRemoteEnvironment(restTemplate, properties, label, state) method to obtain configuration data on the remote server through http. The implementation is also very simple. Display the placeholder in the path of the replacement request, and then assemble the headers. Once assembled, the request can be sent and the result will be returned.
In the above implementation, we see that the obtained configuration information is stored in CompositePropertySource. How do we use it? Another important class to add here is PropertySourceBootstrapConfiguration, which implements the ApplicationContextInitializer interface. This interface will refresh() be called back before the application context is refreshed, thereby performing the initialization operation. The call stack after the application is started is as follows:
SpringApplicationBuilder.run() -> SpringApplication.run() -> SpringApplication.createAndRefreshContext() -> SpringApplication.applyInitializers() -> PropertySourceBootstrapConfiguration.initialize()PropertySourceBootstrapConfiguration
The location method of the above ConfigServicePropertySourceLocator will be called in initialize, so as to ensure that the context can obtain the necessary configuration information before refreshing. Let's take a look at the initialize method:
public class PropertySourceBootstrapConfigurationimplements ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered { private int order = Ordered.HIGHEST_PRECEDENCE + 10; @Autowired(required = false) private List<PropertySourceLocator> propertySourceLocators = new ArrayList<>(); @Override public void initialize(ConfigurableApplicationContext applicationContext){ CompositePropertySource composite = new CompositePropertySource( BOOTSTRAP_PROPERTY_SOURCE_NAME); //Sort the propertySourceLocators array and follow the default AnnotationAwareOrderComparator AnnotationAwareOrderComparator.sort(this.propertySourceLocators); boolean empty = true; //Get the running environment context ConfigurableEnvironment environment = applicationContext.getEnvironment(); for (PropertySourceLocator locator : this.propertySourceLocators) { //Transtraight this.propertySourceLocators PropertySource<?> source = null; source = locator.locate(environment); if (source == null) { continue; } logger.info("Located property source: " + source); //Add source to the linked list of PropertySource composite.addPropertySource(source); empty = false; } //Only if the source is not empty, it will be set to the environment if (!empty) { //Returns the variable form of Environment, which can be performed such as addFirst and addLast MutablePropertySources propertySources = environment.getPropertySources(); String logConfig = environment.resolvePlaceholders("${logging.config:}"); LogFile logFile = LogFile.get(environment); if (propertySources.contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) { //Remove bootstrapProperties propertySources.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME); } //Set propertySources insertPropertySources(propertySources, composite); reinitializeLoggingSystem(environment, logConfig, logFile); setLogLevels(environment); //Dispose multiple actives configuration information of profiles handleIncludedProfiles(environment); } } //...}Let's take a look at what operations are performed in the initialize method.
Returns the variable form of Environment, which can be performed such as addFirst, addLast
Remove bootstrapProperties in propertySources
According to the rules of config server override, set propertySources
Handle configuration information for multiple active profiles
When initialize the initialize method, first traverse the locate method of all the PropertySourceLocator types objects, then put the property values obtained in various ways into the CompositePropertySource , and finally call the insertPropertySources(propertySources, composite) method to set it into Environment. Spring Cloud Context provides PropertySourceBootstrapProperties that overwrite remote properties, and uses this configuration class to determine the priority of the property source.
private void insertPropertySources(MutablePropertySources propertySources, CompositePropertySource composite) { MutablePropertySources incoming = new MutablePropertySources(); incoming.addFirst(composite); PropertySourceBootstrapProperties remoteProperties = new PropertySourceBootstrapProperties(); new RelaxedDataBinder(remoteProperties, "spring.cloud.config") .bind(new PropertySourcesPropertyValues(incoming)); //If local overwrite is not allowed (!remoteProperties.isAllowOverride() || (!remoteProperties.isOverrideNone() && remoteProperties.isOverrideSystemProperties())) { propertySources.addFirst(composite); return; } //overrideNone is true, the external configuration has the lowest priority if (remoteProperties.isOverrideNone()) { propertySources.addLast(composite); return; } if (propertySources .contains(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)) { //Set the priority of external configurations according to overrideSystemProperties if (!remoteProperties.isOverrideSystemProperties()) { propertySources.addAfter( StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, composite); } else { propertySources.addBefore( StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, composite); } } else { propertySources.addLast(composite); }}The above implementation mainly adjusts the priority of multiple configuration sources based on the properties in PropertySourceBootstrapProperties . From its implementation, we can see that the PropertySourceBootstrapProperties object is initialized directly, using the default property value and not injected into what we set in the configuration file.
Repaired implementation:
@Autowired(required = false) private PropertySourceBootstrapProperties remotePropertiesForOverriding; @Override public int getOrder(){ return this.order; private void insertPropertySources(MutablePropertySources propertySources, CompositePropertySource composite) { MutablePropertySources incoming = new MutablePropertySources(); incoming.addFirst(composite); PropertySourceBootstrapProperties remoteProperties = remotePropertiesForOverriding == null ? new PropertySourceBootstrapProperties() : remotePropertiesForOverriding;Summarize
The above is a detailed explanation of the Spring Cloud overriding remote configuration properties example introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support to Wulin.com website!