@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
/ *
* Copyright 2002 - 2016 the original author or authors .
* Copyright 2002 - 2017 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 .
@ -16,7 +16,6 @@
@@ -16,7 +16,6 @@
package org.springframework.context.annotation.configuration ;
import org.junit.Ignore ;
import org.junit.Test ;
import org.springframework.beans.factory.annotation.Value ;
@ -31,28 +30,37 @@ import static org.hamcrest.CoreMatchers.*;
@@ -31,28 +30,37 @@ import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.* ;
/ * *
* A configuration class that registers a placeholder configurer @Bean method
* cannot also have @Value fields . Logically , the config class must be instantiated
* in order to invoke the placeholder configurer bean method , and it is a
* chicken - and - egg problem to process the @Value field .
* A configuration class that registers a non - static placeholder configurer { @code @Bean }
* method cannot also have { @code @Value } fields . Logically , the config class must be
* instantiated in order to invoke the placeholder configurer bean method , and it is a
* chicken - and - egg problem to process the { @code @Value } field .
*
* Therefore , placeholder configurers should be put in separate configuration classes
* as has been done in the test below . Simply said , placeholder configurer @Bean methods
* and @Value fields in the same configuration class are mutually exclusive .
* < p > Therefore , placeholder configurer bean methods should either be { @code static } or
* put in separate configuration classes as has been done in the tests below . Simply said ,
* placeholder configurer { @code @Bean } methods and { @code @Value } fields in the same
* configuration class are mutually exclusive unless the placeholder configurer
* { @code @Bean } method is { @code static } .
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Sam Brannen
* /
public class ConfigurationClassWithPlaceholderConfigurerBeanTests {
/ * *
* Intentionally ignored test proving that a property placeholder bean
* cannot be declared in the same configuration class that has a @Value
* field in need of placeholder replacement . It ' s an obvious chicken - and - egg issue .
* The solution is to do as { @link # valueFieldsAreProcessedWhenPlaceholderConfigurerIsSegregated ( ) }
* Test which proves that a non - static property placeholder bean cannot be declared
* in the same configuration class that has a { @code @Value } field in need of
* placeholder replacement . It ' s an obvious chicken - and - egg issue .
*
* < p > One solution is to do as { @link # valueFieldsAreProcessedWhenPlaceholderConfigurerIsSegregated ( ) }
* does and segregate the two bean definitions across configuration classes .
*
* < p > Another solution is to simply make the { @code @Bean } method for the property
* placeholder { @code static } as in
* { @link # valueFieldsAreProcessedWhenStaticPlaceholderConfigurerIsIntegrated ( ) } .
* /
@Ignore @Test
@Test
@SuppressWarnings ( "resource" )
public void valueFieldsAreNotProcessedWhenPlaceholderConfigurerIsIntegrated ( ) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ( ) ;
ctx . register ( ConfigWithValueFieldAndPlaceholderConfigurer . class ) ;
@ -61,10 +69,25 @@ public class ConfigurationClassWithPlaceholderConfigurerBeanTests {
@@ -61,10 +69,25 @@ public class ConfigurationClassWithPlaceholderConfigurerBeanTests {
System . clearProperty ( "test.name" ) ;
TestBean testBean = ctx . getBean ( TestBean . class ) ;
// Proof that the @Value field did not get set:
assertThat ( testBean . getName ( ) , nullValue ( ) ) ;
}
@Test
@SuppressWarnings ( "resource" )
public void valueFieldsAreProcessedWhenStaticPlaceholderConfigurerIsIntegrated ( ) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ( ) ;
ctx . register ( ConfigWithValueFieldAndStaticPlaceholderConfigurer . class ) ;
System . setProperty ( "test.name" , "foo" ) ;
ctx . refresh ( ) ;
System . clearProperty ( "test.name" ) ;
TestBean testBean = ctx . getBean ( TestBean . class ) ;
assertThat ( testBean . getName ( ) , equalTo ( "foo" ) ) ;
}
@Test
@SuppressWarnings ( "resource" )
public void valueFieldsAreProcessedWhenPlaceholderConfigurerIsSegregated ( ) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ( ) ;
ctx . register ( ConfigWithValueField . class ) ;
@ -78,7 +101,8 @@ public class ConfigurationClassWithPlaceholderConfigurerBeanTests {
@@ -78,7 +101,8 @@ public class ConfigurationClassWithPlaceholderConfigurerBeanTests {
}
@Test
public void valueFieldsResolveToPlaceholderSpecifiedDefaultValue ( ) {
@SuppressWarnings ( "resource" )
public void valueFieldsResolveToPlaceholderSpecifiedDefaultValuesWithPlaceholderConfigurer ( ) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ( ) ;
ctx . register ( ConfigWithValueField . class ) ;
ctx . register ( ConfigWithPlaceholderConfigurer . class ) ;
@ -88,6 +112,18 @@ public class ConfigurationClassWithPlaceholderConfigurerBeanTests {
@@ -88,6 +112,18 @@ public class ConfigurationClassWithPlaceholderConfigurerBeanTests {
assertThat ( testBean . getName ( ) , equalTo ( "bar" ) ) ;
}
@Test
@SuppressWarnings ( "resource" )
public void valueFieldsResolveToPlaceholderSpecifiedDefaultValuesWithoutPlaceholderConfigurer ( ) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext ( ) ;
ctx . register ( ConfigWithValueField . class ) ;
// ctx.register(ConfigWithPlaceholderConfigurer.class);
ctx . refresh ( ) ;
TestBean testBean = ctx . getBean ( TestBean . class ) ;
assertThat ( testBean . getName ( ) , equalTo ( "bar" ) ) ;
}
@Configuration
static class ConfigWithValueField {
@ -129,4 +165,21 @@ public class ConfigurationClassWithPlaceholderConfigurerBeanTests {
@@ -129,4 +165,21 @@ public class ConfigurationClassWithPlaceholderConfigurerBeanTests {
}
}
@Configuration
static class ConfigWithValueFieldAndStaticPlaceholderConfigurer {
@Value ( "${test.name}" )
private String name ;
@Bean
public ITestBean testBean ( ) {
return new TestBean ( this . name ) ;
}
@Bean
public static PropertySourcesPlaceholderConfigurer ppc ( ) {
return new PropertySourcesPlaceholderConfigurer ( ) ;
}
}
}