Use data binding to access spring.profiles .active and .include
Previously, spring.profiles.active and spring.profiles.include were looked up manually. This meant that configuration that used indexes (for example spring.profiles.active[0]=dev) were not bound. As a result, YAML lists did not work. This commit updates ConfigFileApplicationListener to use a RelaxedDataBinder to retrieve the values of spring.profiles.active and spring.profiles.include, thereby reusing the data binding logic that supports property names with indexes. See gh-6995
This commit is contained in:
		
							parent
							
								
									6e79521fff
								
							
						
					
					
						commit
						919d0c6172
					
				| 
						 | 
				
			
			@ -36,6 +36,8 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
 | 
			
		|||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 | 
			
		||||
import org.springframework.boot.SpringApplication;
 | 
			
		||||
import org.springframework.boot.bind.PropertiesConfigurationFactory;
 | 
			
		||||
import org.springframework.boot.bind.PropertySourcesPropertyValues;
 | 
			
		||||
import org.springframework.boot.bind.RelaxedDataBinder;
 | 
			
		||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
 | 
			
		||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
 | 
			
		||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +57,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
 | 
			
		|||
import org.springframework.core.env.EnumerablePropertySource;
 | 
			
		||||
import org.springframework.core.env.MutablePropertySources;
 | 
			
		||||
import org.springframework.core.env.PropertySource;
 | 
			
		||||
import org.springframework.core.env.PropertySources;
 | 
			
		||||
import org.springframework.core.io.DefaultResourceLoader;
 | 
			
		||||
import org.springframework.core.io.Resource;
 | 
			
		||||
import org.springframework.core.io.ResourceLoader;
 | 
			
		||||
| 
						 | 
				
			
			@ -390,8 +393,8 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
 | 
			
		|||
			}
 | 
			
		||||
			// Any pre-existing active profiles set via property sources (e.g. System
 | 
			
		||||
			// properties) take precedence over those added in config files.
 | 
			
		||||
			Set<Profile> activeProfiles = getProfilesForValue(
 | 
			
		||||
					this.environment.getProperty(ACTIVE_PROFILES_PROPERTY));
 | 
			
		||||
			Set<Profile> activeProfiles = bindSpringProfiles(
 | 
			
		||||
					this.environment.getPropertySources()).getActiveProfiles();
 | 
			
		||||
			maybeActivateProfiles(activeProfiles);
 | 
			
		||||
			return activeProfiles;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -506,12 +509,23 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		private void handleProfileProperties(PropertySource<?> propertySource) {
 | 
			
		||||
			Set<Profile> activeProfiles = getProfilesForValue(
 | 
			
		||||
					propertySource.getProperty(ACTIVE_PROFILES_PROPERTY));
 | 
			
		||||
			maybeActivateProfiles(activeProfiles);
 | 
			
		||||
			Set<Profile> includeProfiles = getProfilesForValue(
 | 
			
		||||
					propertySource.getProperty(INCLUDE_PROFILES_PROPERTY));
 | 
			
		||||
			addProfiles(includeProfiles);
 | 
			
		||||
			SpringProfiles springProfiles = bindSpringProfiles(propertySource);
 | 
			
		||||
			maybeActivateProfiles(springProfiles.getActiveProfiles());
 | 
			
		||||
			addProfiles(springProfiles.getIncludeProfiles());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private SpringProfiles bindSpringProfiles(PropertySource<?> propertySource) {
 | 
			
		||||
			MutablePropertySources propertySources = new MutablePropertySources();
 | 
			
		||||
			propertySources.addFirst(propertySource);
 | 
			
		||||
			return bindSpringProfiles(propertySources);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private SpringProfiles bindSpringProfiles(PropertySources propertySources) {
 | 
			
		||||
			SpringProfiles springProfiles = new SpringProfiles();
 | 
			
		||||
			RelaxedDataBinder dataBinder = new RelaxedDataBinder(springProfiles,
 | 
			
		||||
					"spring.profiles");
 | 
			
		||||
			dataBinder.bind(new PropertySourcesPropertyValues(propertySources));
 | 
			
		||||
			return springProfiles;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void maybeActivateProfiles(Set<Profile> profiles) {
 | 
			
		||||
| 
						 | 
				
			
			@ -540,16 +554,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private Set<Profile> getProfilesForValue(Object property) {
 | 
			
		||||
			String value = (property == null ? null : property.toString());
 | 
			
		||||
			Set<String> profileNames = asResolvedSet(value, null);
 | 
			
		||||
			Set<Profile> profiles = new LinkedHashSet<Profile>();
 | 
			
		||||
			for (String profileName : profileNames) {
 | 
			
		||||
				profiles.add(new Profile(profileName));
 | 
			
		||||
			}
 | 
			
		||||
			return profiles;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void addProfiles(Set<Profile> profiles) {
 | 
			
		||||
			for (Profile profile : profiles) {
 | 
			
		||||
				this.profiles.add(profile);
 | 
			
		||||
| 
						 | 
				
			
			@ -750,4 +754,48 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Holder for {@code spring.profiles} properties.
 | 
			
		||||
	 */
 | 
			
		||||
	static final class SpringProfiles {
 | 
			
		||||
 | 
			
		||||
		private List<String> active = new ArrayList<String>();
 | 
			
		||||
 | 
			
		||||
		private List<String> include = new ArrayList<String>();
 | 
			
		||||
 | 
			
		||||
		public List<String> getActive() {
 | 
			
		||||
			return this.active;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void setActive(List<String> active) {
 | 
			
		||||
			this.active = active;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public List<String> getInclude() {
 | 
			
		||||
			return this.include;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void setInclude(List<String> include) {
 | 
			
		||||
			this.include = include;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Set<Profile> getActiveProfiles() {
 | 
			
		||||
			return asProfileSet(this.active);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Set<Profile> getIncludeProfiles() {
 | 
			
		||||
			return asProfileSet(this.include);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private Set<Profile> asProfileSet(List<String> profileNames) {
 | 
			
		||||
			List<Profile> profiles = new ArrayList<Profile>();
 | 
			
		||||
			for (String profileName : profileNames) {
 | 
			
		||||
				profiles.add(new Profile(profileName));
 | 
			
		||||
			}
 | 
			
		||||
			Collections.reverse(profiles);
 | 
			
		||||
			return new LinkedHashSet<Profile>(profiles);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue