Skip to content

Commit 7535e24

Browse files
committed
Warn re Environment construction and instance vars
- Add warning regarding access to default instance variable values during AbstractEnvironment#customizePropertySources callback - Polish AbstractEnvironment Javadoc and formatting Issue: SPR-9013
1 parent 80dd32e commit 7535e24

File tree

1 file changed

+56
-17
lines changed

1 file changed

+56
-17
lines changed

org.springframework.core/src/main/java/org/springframework/core/env/AbstractEnvironment.java

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,22 +16,23 @@
1616

1717
package org.springframework.core.env;
1818

19-
import static java.lang.String.format;
20-
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
21-
import static org.springframework.util.StringUtils.trimAllWhitespace;
22-
2319
import java.security.AccessControlException;
20+
2421
import java.util.Collections;
2522
import java.util.LinkedHashSet;
2623
import java.util.Map;
2724
import java.util.Set;
2825

2926
import org.apache.commons.logging.Log;
3027
import org.apache.commons.logging.LogFactory;
28+
3129
import org.springframework.core.convert.support.ConfigurableConversionService;
3230
import org.springframework.util.Assert;
3331
import org.springframework.util.StringUtils;
3432

33+
import static java.lang.String.*;
34+
import static org.springframework.util.StringUtils.*;
35+
3536
/**
3637
* Abstract base class for {@link Environment} implementations. Supports the notion of
3738
* reserved default profile names and enables specifying active and default profiles
@@ -89,19 +90,39 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
8990
protected final Log logger = LogFactory.getLog(getClass());
9091

9192
private Set<String> activeProfiles = new LinkedHashSet<String>();
92-
private Set<String> defaultProfiles = new LinkedHashSet<String>(this.getReservedDefaultProfiles());
9393

94-
private final MutablePropertySources propertySources = new MutablePropertySources(logger);
95-
private final ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(propertySources);
94+
private Set<String> defaultProfiles =
95+
new LinkedHashSet<String>(this.getReservedDefaultProfiles());
9696

97+
private final MutablePropertySources propertySources =
98+
new MutablePropertySources(this.logger);
9799

100+
private final ConfigurablePropertyResolver propertyResolver =
101+
new PropertySourcesPropertyResolver(this.propertySources);
102+
103+
104+
/**
105+
* Create a new {@code Environment} instance, calling back to
106+
* {@link #customizePropertySources(MutablePropertySources)} during construction to
107+
* allow subclasses to contribute or manipulate {@link PropertySource} instances as
108+
* appropriate.
109+
* @see #customizePropertySources(MutablePropertySources)
110+
*/
98111
public AbstractEnvironment() {
99112
String name = this.getClass().getSimpleName();
100-
logger.debug(String.format("Initializing new %s", name));
101-
this.customizePropertySources(propertySources);
102-
logger.debug(String.format("Initialized %s with PropertySources %s", name, propertySources));
113+
if (this.logger.isDebugEnabled()) {
114+
this.logger.debug(format("Initializing new %s", name));
115+
}
116+
117+
this.customizePropertySources(this.propertySources);
118+
119+
if (this.logger.isDebugEnabled()) {
120+
this.logger.debug(format(
121+
"Initialized %s with PropertySources %s", name, this.propertySources));
122+
}
103123
}
104124

125+
105126
/**
106127
* Customize the set of {@link PropertySource} objects to be searched by this
107128
* {@code Environment} during calls to {@link #getProperty(String)} and related
@@ -163,6 +184,17 @@ public AbstractEnvironment() {
163184
* env.getPropertySources().addLast(new PropertySourceX(...));
164185
* </pre>
165186
*
187+
* <h2>A warning about instance variable access</h2>
188+
* Instance variables declared in subclasses and having default initial values should
189+
* <em>not</em> be accessed from within this method. Due to Java object creation
190+
* lifecycle constraints, any initial value will not yet be assigned when this
191+
* callback is invoked by the {@link #AbstractEnvironment()} constructor, which may
192+
* lead to a {@code NullPointerException} or other problems. If you need to access
193+
* default values of instance variables, leave this method as a no-op and perform
194+
* property source manipulation and instance variable access directly within the
195+
* subclass constructor. Note that <em>assigning</em> values to instance variables is
196+
* not problematic; it is only attempting to read default values that must be avoided.
197+
*
166198
* @see MutablePropertySources
167199
* @see PropertySourcesPropertyResolver
168200
* @see org.springframework.context.ApplicationContextInitializer
@@ -217,7 +249,9 @@ public void setActiveProfiles(String... profiles) {
217249
}
218250

219251
public void addActiveProfile(String profile) {
220-
logger.debug(String.format("Activating profile '%s'", profile));
252+
if (this.logger.isDebugEnabled()) {
253+
this.logger.debug(format("Activating profile '%s'", profile));
254+
}
221255
this.validateProfile(profile);
222256
this.activeProfiles.add(profile);
223257
}
@@ -312,8 +346,10 @@ protected String getSystemAttribute(String variableName) {
312346
}
313347
catch (AccessControlException ex) {
314348
if (logger.isInfoEnabled()) {
315-
logger.info(format("Caught AccessControlException when accessing system environment variable " +
316-
"[%s]; its value will be returned [null]. Reason: %s", variableName, ex.getMessage()));
349+
logger.info(format("Caught AccessControlException when " +
350+
"accessing system environment variable [%s]; its " +
351+
"value will be returned [null]. Reason: %s",
352+
variableName, ex.getMessage()));
317353
}
318354
return null;
319355
}
@@ -338,8 +374,10 @@ protected String getSystemAttribute(String propertyName) {
338374
}
339375
catch (AccessControlException ex) {
340376
if (logger.isInfoEnabled()) {
341-
logger.info(format("Caught AccessControlException when accessing system property " +
342-
"[%s]; its value will be returned [null]. Reason: %s", propertyName, ex.getMessage()));
377+
logger.info(format("Caught AccessControlException when " +
378+
"accessing system property [%s]; its value will be " +
379+
"returned [null]. Reason: %s",
380+
propertyName, ex.getMessage()));
343381
}
344382
return null;
345383
}
@@ -428,7 +466,8 @@ public void setValueSeparator(String valueSeparator) {
428466
@Override
429467
public String toString() {
430468
return format("%s {activeProfiles=%s, defaultProfiles=%s, propertySources=%s}",
431-
getClass().getSimpleName(), this.activeProfiles, this.defaultProfiles, this.propertySources);
469+
getClass().getSimpleName(), this.activeProfiles, this.defaultProfiles,
470+
this.propertySources);
432471
}
433472

434473
}

0 commit comments

Comments
 (0)