mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Automatically detect 'development' profile
Detect when an application is running in development (by the presence of a build file) and automatically add a 'development' profile. Additional detectors can be developed by implementing the `ProfileDetector` interface and registering with the `SpringApplication` Fixes gh-296
This commit is contained in:
parent
643295cc3c
commit
a97bcfe3cd
@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@ -43,6 +44,8 @@ public class SampleSimpleApplication implements CommandLineRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
SpringApplication.run(SampleSimpleApplication.class, args);
|
ConfigurableApplicationContext context = SpringApplication.run(
|
||||||
|
SampleSimpleApplication.class, args);
|
||||||
|
System.out.println(context.getEnvironment().acceptsProfiles("development"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2014 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ProfileDetector} that attempts to detect when the application is being developed
|
||||||
|
* and adds a 'development' profile.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class DevelopmentProfileDetector implements ProfileDetector {
|
||||||
|
|
||||||
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
private static final String DEFAULT_PROFILE_NAME = "development";
|
||||||
|
|
||||||
|
private static final String EXECUTABLE_JAR_CLASS = "org.springframework.boot.loader.Launcher";
|
||||||
|
|
||||||
|
private static final String[] DEVELOPMENT_TIME_FILES = { "pom.xml", "build.gradle",
|
||||||
|
"build.xml" };
|
||||||
|
|
||||||
|
private final String profileName;
|
||||||
|
|
||||||
|
public DevelopmentProfileDetector() {
|
||||||
|
this(DEFAULT_PROFILE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DevelopmentProfileDetector(String profileName) {
|
||||||
|
Assert.notNull(profileName, "ProfileName must not be null");
|
||||||
|
this.profileName = profileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addDetectedProfiles(ConfigurableEnvironment environment) {
|
||||||
|
if (!isPackageAsJar() && isRunningInDevelopmentDirectory()) {
|
||||||
|
environment.addActiveProfile(this.profileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isPackageAsJar() {
|
||||||
|
if (ClassUtils.isPresent(EXECUTABLE_JAR_CLASS, null)) {
|
||||||
|
this.logger.debug("Development profile not detected: "
|
||||||
|
+ "running inside executable jar");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String command = System.getProperty("sun.java.command");
|
||||||
|
if (StringUtils.hasLength(command) && command.toLowerCase().contains(".jar")) {
|
||||||
|
this.logger.debug("Development profile not detected: started from a jar");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRunningInDevelopmentDirectory() {
|
||||||
|
File userDir = getUserDir();
|
||||||
|
if (userDir != null && userDir.exists()) {
|
||||||
|
for (String developementTimeFile : DEVELOPMENT_TIME_FILES) {
|
||||||
|
if (new File(userDir, developementTimeFile).exists()) {
|
||||||
|
this.logger.debug("Development profile detected: file "
|
||||||
|
+ developementTimeFile + " present");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File getUserDir() {
|
||||||
|
String userDir = System.getProperty("user.dir");
|
||||||
|
return (userDir == null ? null : new File(userDir));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2014 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot;
|
||||||
|
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strategy interface that can be used to detect active profiles.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public interface ProfileDetector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any detected profiles to the specified environment.
|
||||||
|
* @param environment the environment
|
||||||
|
*/
|
||||||
|
void addDetectedProfiles(ConfigurableEnvironment environment);
|
||||||
|
|
||||||
|
}
|
@ -158,6 +158,9 @@ public class SpringApplication {
|
|||||||
private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
|
private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
|
||||||
"org.springframework.web.context.ConfigurableWebApplicationContext" };
|
"org.springframework.web.context.ConfigurableWebApplicationContext" };
|
||||||
|
|
||||||
|
private static final List<ProfileDetector> DEFAULT_PROFILE_DETECTORS = Arrays
|
||||||
|
.<ProfileDetector> asList(new DevelopmentProfileDetector());
|
||||||
|
|
||||||
private final Log log = LogFactory.getLog(getClass());
|
private final Log log = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
private final Set<Object> sources = new LinkedHashSet<Object>();
|
private final Set<Object> sources = new LinkedHashSet<Object>();
|
||||||
@ -190,6 +193,8 @@ public class SpringApplication {
|
|||||||
|
|
||||||
private Set<String> profiles = new HashSet<String>();
|
private Set<String> profiles = new HashSet<String>();
|
||||||
|
|
||||||
|
private List<ProfileDetector> profileDetectors = DEFAULT_PROFILE_DETECTORS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crate a new {@link SpringApplication} instance. The application context will load
|
* Crate a new {@link SpringApplication} instance. The application context will load
|
||||||
* beans from the specified sources (see {@link SpringApplication class-level}
|
* beans from the specified sources (see {@link SpringApplication class-level}
|
||||||
@ -308,9 +313,7 @@ public class SpringApplication {
|
|||||||
// Create and configure the environment
|
// Create and configure the environment
|
||||||
ConfigurableEnvironment environment = getOrCreateEnvironment();
|
ConfigurableEnvironment environment = getOrCreateEnvironment();
|
||||||
addPropertySources(environment, args);
|
addPropertySources(environment, args);
|
||||||
for (String profile : this.profiles) {
|
setupProfiles(environment);
|
||||||
environment.addActiveProfile(profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify listeners of the environment creation
|
// Notify listeners of the environment creation
|
||||||
multicaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this,
|
multicaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this,
|
||||||
@ -461,6 +464,15 @@ public class SpringApplication {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setupProfiles(ConfigurableEnvironment environment) {
|
||||||
|
for (String profile : this.profiles) {
|
||||||
|
environment.addActiveProfile(profile);
|
||||||
|
}
|
||||||
|
for (ProfileDetector profileDetector : this.profileDetectors) {
|
||||||
|
profileDetector.addDetectedProfiles(environment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print a simple banner message to the console. Subclasses can override this method
|
* Print a simple banner message to the console. Subclasses can override this method
|
||||||
* to provide additional or alternative banners.
|
* to provide additional or alternative banners.
|
||||||
@ -740,11 +752,23 @@ public class SpringApplication {
|
|||||||
/**
|
/**
|
||||||
* Set additional profile values to use (on top of those set in system or command line
|
* Set additional profile values to use (on top of those set in system or command line
|
||||||
* properties).
|
* properties).
|
||||||
*
|
|
||||||
* @param profiles the additional profiles to set
|
* @param profiles the additional profiles to set
|
||||||
*/
|
*/
|
||||||
public void setAdditionalProfiles(Collection<String> profiles) {
|
public void setAdditionalProfiles(String... profiles) {
|
||||||
this.profiles = new LinkedHashSet<String>(profiles);
|
this.profiles = new LinkedHashSet<String>(Arrays.asList(profiles));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link ProfileDetector}s that will be used to attempt to detect
|
||||||
|
* {@link Environment#acceptsProfiles(String...) active profiles}.
|
||||||
|
* {@link DevelopmentProfileDetector} is used.
|
||||||
|
* @param profileDetectors the profile detectors
|
||||||
|
* @see #setAdditionalProfiles(String...)
|
||||||
|
*/
|
||||||
|
public void setProfileDetectors(ProfileDetector... profileDetectors) {
|
||||||
|
Assert.notNull(profileDetectors, "Profile detectors must not be null");
|
||||||
|
this.profileDetectors = new ArrayList<ProfileDetector>(
|
||||||
|
Arrays.asList(profileDetectors));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +28,7 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||||
|
import org.springframework.boot.ProfileDetector;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.context.initializer.ParentContextApplicationContextInitializer;
|
import org.springframework.boot.context.initializer.ParentContextApplicationContextInitializer;
|
||||||
import org.springframework.boot.context.initializer.ServletContextApplicationContextInitializer;
|
import org.springframework.boot.context.initializer.ServletContextApplicationContextInitializer;
|
||||||
@ -389,14 +390,26 @@ public class SpringApplicationBuilder {
|
|||||||
*/
|
*/
|
||||||
public SpringApplicationBuilder profiles(String... profiles) {
|
public SpringApplicationBuilder profiles(String... profiles) {
|
||||||
this.additionalProfiles.addAll(Arrays.asList(profiles));
|
this.additionalProfiles.addAll(Arrays.asList(profiles));
|
||||||
this.application.setAdditionalProfiles(this.additionalProfiles);
|
this.application.setAdditionalProfiles(this.additionalProfiles
|
||||||
|
.toArray(new String[this.additionalProfiles.size()]));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the {@link ProfileDetector}s that should be used for this app.
|
||||||
|
* @param profileDetectors the profile detectors to set
|
||||||
|
* @return the current builder
|
||||||
|
*/
|
||||||
|
public SpringApplicationBuilder profileDetectors(ProfileDetector... profileDetectors) {
|
||||||
|
this.application.setProfileDetectors(profileDetectors);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SpringApplicationBuilder additionalProfiles(
|
private SpringApplicationBuilder additionalProfiles(
|
||||||
Collection<String> additionalProfiles) {
|
Collection<String> additionalProfiles) {
|
||||||
this.additionalProfiles = new LinkedHashSet<String>(additionalProfiles);
|
this.additionalProfiles = new LinkedHashSet<String>(additionalProfiles);
|
||||||
this.application.setAdditionalProfiles(additionalProfiles);
|
this.application.setAdditionalProfiles(additionalProfiles
|
||||||
|
.toArray(new String[additionalProfiles.size()]));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,8 +61,7 @@ public class SpringApplicationContextLoader extends AbstractContextLoader {
|
|||||||
SpringApplication application = new SpringApplication();
|
SpringApplication application = new SpringApplication();
|
||||||
application.setSources(getSources(mergedConfig));
|
application.setSources(getSources(mergedConfig));
|
||||||
if (!ObjectUtils.isEmpty(mergedConfig.getActiveProfiles())) {
|
if (!ObjectUtils.isEmpty(mergedConfig.getActiveProfiles())) {
|
||||||
application.setAdditionalProfiles(Arrays.asList(mergedConfig
|
application.setAdditionalProfiles(mergedConfig.getActiveProfiles());
|
||||||
.getActiveProfiles()));
|
|
||||||
}
|
}
|
||||||
application.setDefaultProperties(getArgs(mergedConfig));
|
application.setDefaultProperties(getArgs(mergedConfig));
|
||||||
List<ApplicationContextInitializer<?>> initializers = getInitializers(
|
List<ApplicationContextInitializer<?>> initializers = getInitializers(
|
||||||
|
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2014 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.TemporaryFolder;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link DevelopmentProfileDetector}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class DevelopmentProfileDetectorTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||||
|
|
||||||
|
private TestDevelopmentProfileDetector detector;
|
||||||
|
|
||||||
|
private ConfigurableEnvironment environment;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
this.detector = new TestDevelopmentProfileDetector();
|
||||||
|
this.environment = mock(ConfigurableEnvironment.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void notFound() {
|
||||||
|
this.detector.addDetectedProfiles(this.environment);
|
||||||
|
verifyZeroInteractions(this.environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void foundDueToMavenBuild() throws Exception {
|
||||||
|
this.temporaryFolder.newFile("pom.xml").createNewFile();
|
||||||
|
this.detector.addDetectedProfiles(this.environment);
|
||||||
|
verify(this.environment).addActiveProfile("development");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void foundDueToGradleBuild() throws Exception {
|
||||||
|
this.temporaryFolder.newFile("build.gradle").createNewFile();
|
||||||
|
this.detector.addDetectedProfiles(this.environment);
|
||||||
|
verify(this.environment).addActiveProfile("development");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void foundDueToAntBuild() throws Exception {
|
||||||
|
this.temporaryFolder.newFile("build.xml").createNewFile();
|
||||||
|
this.detector.addDetectedProfiles(this.environment);
|
||||||
|
verify(this.environment).addActiveProfile("development");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void differentProfileName() throws Exception {
|
||||||
|
this.detector = new TestDevelopmentProfileDetector("different");
|
||||||
|
this.temporaryFolder.newFile("pom.xml").createNewFile();
|
||||||
|
this.detector.addDetectedProfiles(this.environment);
|
||||||
|
verify(this.environment).addActiveProfile("different");
|
||||||
|
verifyNoMoreInteractions(this.environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void notFoundWhenStartedFromJar() throws Exception {
|
||||||
|
System.setProperty("sun.java.command", "something.jar");
|
||||||
|
this.temporaryFolder.newFile("pom.xml").createNewFile();
|
||||||
|
this.detector.setSkipPackageAsJar(false);
|
||||||
|
this.detector.addDetectedProfiles(this.environment);
|
||||||
|
verifyZeroInteractions(this.environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestDevelopmentProfileDetector extends DevelopmentProfileDetector {
|
||||||
|
|
||||||
|
private boolean skipPackageAsJar = true;
|
||||||
|
|
||||||
|
public TestDevelopmentProfileDetector() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestDevelopmentProfileDetector(String profileName) {
|
||||||
|
super(profileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSkipPackageAsJar(boolean skipPackageAsJar) {
|
||||||
|
this.skipPackageAsJar = skipPackageAsJar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isPackageAsJar() {
|
||||||
|
if (this.skipPackageAsJar) {
|
||||||
|
// Unfortunately surefire uses a jar so we need to stub this out
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.isPackageAsJar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected File getUserDir() {
|
||||||
|
return DevelopmentProfileDetectorTests.this.temporaryFolder.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -409,6 +409,29 @@ public class SpringApplicationTests {
|
|||||||
assertThat(System.getProperty("java.awt.headless"), equalTo("false"));
|
assertThat(System.getProperty("java.awt.headless"), equalTo("false"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setAdditionalProfiles() throws Exception {
|
||||||
|
TestSpringApplication application = new TestSpringApplication(ExampleConfig.class);
|
||||||
|
application.setWebEnvironment(false);
|
||||||
|
application.setAdditionalProfiles("mine");
|
||||||
|
this.context = application.run();
|
||||||
|
assertThat(this.context.getEnvironment().acceptsProfiles("mine"), equalTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setProfileDetectors() throws Exception {
|
||||||
|
TestSpringApplication application = new TestSpringApplication(ExampleConfig.class);
|
||||||
|
application.setWebEnvironment(false);
|
||||||
|
application.setProfileDetectors(new ProfileDetector() {
|
||||||
|
@Override
|
||||||
|
public void addDetectedProfiles(ConfigurableEnvironment environment) {
|
||||||
|
environment.addActiveProfile("mine");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.context = application.run();
|
||||||
|
assertThat(this.context.getEnvironment().acceptsProfiles("mine"), equalTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasPropertySource(ConfigurableEnvironment environment,
|
private boolean hasPropertySource(ConfigurableEnvironment environment,
|
||||||
Class<?> propertySourceClass, String name) {
|
Class<?> propertySourceClass, String name) {
|
||||||
for (PropertySource<?> source : environment.getPropertySources()) {
|
for (PropertySource<?> source : environment.getPropertySources()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user