forked from spring-projects/spring-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allows a convenient mechanism for contributing a PropertySource to the enclosing Spring Environment. See @propertysource Javadoc for complete details and PropertySourceAnnotationTests for examples. Issue: SPR-8314
- Loading branch information
Showing
6 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
...ramework.context/src/main/java/org/springframework/context/annotation/PropertySource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* Copyright 2002-2011 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.context.annotation; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Annotation providing a convenient and declarative mechanism for adding a | ||
* {@link org.springframework.core.env.PropertySource PropertySource} to Spring's | ||
* {@link org.springframework.core.env.Environment Environment}. To be used in | ||
* conjunction with @{@link Configuration} classes. | ||
* | ||
* <h3>Example usage</h3> | ||
* <p>Given a file {@code app.properties} containing the key/value pair | ||
* {@code testbean.name=myTestBean}, the following {@code @Configuration} class | ||
* uses {@code @PropertySource} to contribute {@code app.properties} to the | ||
* {@code Environment}'s set of {@code PropertySources}. | ||
* | ||
* <pre> | ||
* @Configuration | ||
* @PropertySource("classpath:/com/myco/app.properties") | ||
* public class AppConfig { | ||
* @Autowired | ||
* Environment env; | ||
* | ||
* @Bean | ||
* public TestBean testBean() { | ||
* TestBean testBean = new TestBean(); | ||
* testBean.setName(env.getProperty("testbean.name")); | ||
* return testBean; | ||
* } | ||
* }</pre> | ||
* | ||
* Notice that the {@code Environment} object is @{@link Autowired} into the | ||
* configuration class and then used when populating the {@code TestBean} | ||
* object. Given the configuration above, a call to {@code testBean.getName()} will | ||
* return "myTestBean". | ||
* | ||
* <h3>A note on property overriding with @PropertySource</h3> | ||
* In cases where a given property key exists in more than one {@code .properties} | ||
* file, the last {@code @PropertySource} annotation processed will 'win' and override. | ||
* | ||
* For example, given two properties files {@code a.properties} and | ||
* {@code b.properties}, consider the following two configuration classes | ||
* that reference them with {@code @PropertySource} annotations: | ||
* | ||
* <pre> | ||
* @Configuration | ||
* @PropertySource("classpath:/com/myco/a.properties") | ||
* public class ConfigA { } | ||
* | ||
* @Configuration | ||
* @PropertySource("classpath:/com/myco/b.properties") | ||
* public class ConfigB { } | ||
* </pre> | ||
* | ||
* The override ordering depends on the order in which these classes are registered | ||
* with the application context. | ||
* <pre> | ||
* AnnotationConfigApplicationContext ctx = | ||
* new AnnotationConfigApplicationContext(); | ||
* ctx.register(ConfigA.class); | ||
* ctx.register(ConfigB.class); | ||
* ctx.refresh(); | ||
* </pre> | ||
* | ||
* In the scenario above, the properties in {@code b.properties} will override any | ||
* duplicates that exist in {@code a.properties}, because {@code ConfigB} was registered | ||
* last. | ||
* | ||
* <p>In certain situations, it may not be possible or practical to tightly control | ||
* property source ordering when using {@code @ProperySource} annotations. For example, | ||
* if the {@code @Configuration} classes above were registered via component-scanning, | ||
* the ordering is difficult to predict. In such cases - and if overriding is important - | ||
* it is recommended that the user fall back to using the programmatic PropertySource API. | ||
* See {@link org.springframework.core.env.ConfigurableEnvironment ConfigurableEnvironment} and | ||
* {@link org.springframework.core.env.MutablePropertySources MutablePropertySources} Javadoc | ||
* for details. | ||
* | ||
* @author Chris Beams | ||
* @since 3.1 | ||
*/ | ||
@Target(ElementType.TYPE) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Documented | ||
public @interface PropertySource { | ||
|
||
/** | ||
* Indicate the name of this PropertySource. If omitted, a name | ||
* will be generated based on the description of the underlying | ||
* resource. | ||
* @see org.springframework.core.env.PropertySource#getName() | ||
* @see org.springframework.core.io.Resource#getDescription() | ||
*/ | ||
String name() default ""; | ||
|
||
/** | ||
* Indicate the resource location of the properties file to be loaded. | ||
* For example, {@code "classpath:/com/myco/app.properties"} or | ||
* {@code "file:/path/to/file"}. Note that resource location wildcards | ||
* are not permitted, and that a location must evaluate to exactly one | ||
* {@code .properties} resource. | ||
*/ | ||
String value(); | ||
|
||
} |
125 changes: 125 additions & 0 deletions
125
...t/src/test/java/org/springframework/context/annotation/PropertySourceAnnotationTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* Copyright 2002-2011 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.context.annotation; | ||
|
||
import static org.hamcrest.CoreMatchers.equalTo; | ||
import static org.hamcrest.CoreMatchers.is; | ||
import static org.junit.Assert.assertThat; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
import java.util.Iterator; | ||
|
||
import javax.inject.Inject; | ||
|
||
import org.junit.Test; | ||
import org.springframework.core.env.Environment; | ||
import org.springframework.core.env.MutablePropertySources; | ||
|
||
import test.beans.TestBean; | ||
|
||
/** | ||
* Tests the processing of @PropertySource annotations on @Configuration classes. | ||
* | ||
* @author Chris Beams | ||
* @since 3.1 | ||
*/ | ||
public class PropertySourceAnnotationTests { | ||
|
||
@Test | ||
public void withExplicitName() { | ||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); | ||
ctx.register(ConfigWithExplicitName.class); | ||
ctx.refresh(); | ||
assertTrue("property source p1 was not added", | ||
ctx.getEnvironment().getPropertySources().contains("p1")); | ||
assertThat(ctx.getBean(TestBean.class).getName(), equalTo("p1TestBean")); | ||
|
||
// assert that the property source was added last to the set of sources | ||
String name; | ||
MutablePropertySources sources = ctx.getEnvironment().getPropertySources(); | ||
Iterator<org.springframework.core.env.PropertySource<?>> iterator = sources.iterator(); | ||
do { | ||
name = iterator.next().getName(); | ||
} | ||
while(iterator.hasNext()); | ||
|
||
assertThat(name, is("p1")); | ||
} | ||
|
||
@Test | ||
public void withImplicitName() { | ||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); | ||
ctx.register(ConfigWithImplicitName.class); | ||
ctx.refresh(); | ||
assertTrue("property source p1 was not added", | ||
ctx.getEnvironment().getPropertySources().contains("class path resource [org/springframework/context/annotation/p1.properties]")); | ||
assertThat(ctx.getBean(TestBean.class).getName(), equalTo("p1TestBean")); | ||
} | ||
|
||
/** | ||
* Tests the LIFO behavior of @PropertySource annotaitons. | ||
* The last one registered should 'win'. | ||
*/ | ||
@Test | ||
public void orderingIsLifo() { | ||
{ | ||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); | ||
ctx.register(ConfigWithImplicitName.class, P2Config.class); | ||
ctx.refresh(); | ||
// p2 should 'win' as it was registered last | ||
assertThat(ctx.getBean(TestBean.class).getName(), equalTo("p2TestBean")); | ||
} | ||
|
||
{ | ||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); | ||
ctx.register(P2Config.class, ConfigWithImplicitName.class); | ||
ctx.refresh(); | ||
// p1 should 'win' as it was registered last | ||
assertThat(ctx.getBean(TestBean.class).getName(), equalTo("p1TestBean")); | ||
} | ||
} | ||
|
||
|
||
@Configuration | ||
@PropertySource(name="p1", value="classpath:org/springframework/context/annotation/p1.properties") | ||
static class ConfigWithExplicitName { | ||
@Inject Environment env; | ||
|
||
@Bean | ||
public TestBean testBean() { | ||
return new TestBean(env.getProperty("testbean.name")); | ||
} | ||
} | ||
|
||
|
||
@Configuration | ||
@PropertySource("classpath:org/springframework/context/annotation/p1.properties") | ||
static class ConfigWithImplicitName { | ||
@Inject Environment env; | ||
|
||
@Bean | ||
public TestBean testBean() { | ||
return new TestBean(env.getProperty("testbean.name")); | ||
} | ||
} | ||
|
||
|
||
@Configuration | ||
@PropertySource("classpath:org/springframework/context/annotation/p2.properties") | ||
static class P2Config { | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
...pringframework.context/src/test/java/org/springframework/context/annotation/p1.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
testbean.name=p1TestBean |
1 change: 1 addition & 0 deletions
1
...pringframework.context/src/test/java/org/springframework/context/annotation/p2.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
testbean.name=p2TestBean |