Browse Source

Support `@Name` with JavaBean-based configuration properties

See gh-39452
pull/41596/head
BenchmarkingBuffalo 2 years ago committed by Andy Wilkinson
parent
commit
a305e2d1bd
  1. 12
      spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java
  2. 7
      spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Name.java
  3. 26
      spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/JavaBeanBinderTests.java
  4. 19
      spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/KotlinConfigurationPropertiesTests.kt

12
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java

@ -46,6 +46,7 @@ import org.springframework.core.ResolvableType; @@ -46,6 +46,7 @@ import org.springframework.core.ResolvableType;
*
* @author Phillip Webb
* @author Madhura Bhave
* @author Lasse Wulff
*/
class JavaBeanBinder implements DataObjectBinder {
@ -92,7 +93,7 @@ class JavaBeanBinder implements DataObjectBinder { @@ -92,7 +93,7 @@ class JavaBeanBinder implements DataObjectBinder {
private <T> boolean bind(BeanSupplier<T> beanSupplier, DataObjectPropertyBinder propertyBinder,
BeanProperty property) {
String propertyName = property.getName();
String propertyName = determinePropertyName(property);
ResolvableType type = property.getType();
Supplier<Object> value = property.getValue(beanSupplier);
Annotation[] annotations = property.getAnnotations();
@ -110,6 +111,15 @@ class JavaBeanBinder implements DataObjectBinder { @@ -110,6 +111,15 @@ class JavaBeanBinder implements DataObjectBinder {
return true;
}
private String determinePropertyName(BeanProperty property) {
return Arrays.stream((property.getAnnotations() != null) ? property.getAnnotations() : new Annotation[0])
.filter((annotation) -> annotation.annotationType() == Name.class)
.findFirst()
.map(Name.class::cast)
.map(Name::value)
.orElse(property.getName());
}
/**
* The properties of a bean that may be bound.
*/

7
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Name.java

@ -23,15 +23,16 @@ import java.lang.annotation.RetentionPolicy; @@ -23,15 +23,16 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that can be used to specify the name when binding to an immutable property.
* This annotation may be required when binding to names that clash with reserved language
* Annotation that can be used to specify the name when binding to a property. This
* annotation may be required when binding to names that clash with reserved language
* keywords.
*
* @author Phillip Webb
* @author Lasse Wulff
* @since 2.4.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Documented
public @interface Name {

26
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/JavaBeanBinderTests.java

@ -52,6 +52,7 @@ import static org.assertj.core.api.Assertions.entry; @@ -52,6 +52,7 @@ import static org.assertj.core.api.Assertions.entry;
* @author Phillip Webb
* @author Madhura Bhave
* @author Andy Wilkinson
* @author Lasse Wulff
*/
class JavaBeanBinderTests {
@ -74,6 +75,16 @@ class JavaBeanBinderTests { @@ -74,6 +75,16 @@ class JavaBeanBinderTests {
assertThat(bean.getEnumValue()).isEqualTo(ExampleEnum.FOO_BAR);
}
@Test
void bindRenamedPropertyToClassBean() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("renamed.public", "alpha");
this.sources.add(source);
ExampleRenamedPropertyBean bean = this.binder.bind("renamed", Bindable.of(ExampleRenamedPropertyBean.class))
.get();
assertThat(bean.getExampleProperty()).isEqualTo("alpha");
}
@Test
void bindToClassWhenHasNoPrefixShouldCreateBoundBean() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
@ -648,6 +659,21 @@ class JavaBeanBinderTests { @@ -648,6 +659,21 @@ class JavaBeanBinderTests {
}
static class ExampleRenamedPropertyBean {
@Name("public")
private String exampleProperty;
String getExampleProperty() {
return this.exampleProperty;
}
void setExampleProperty(String exampleProperty) {
this.exampleProperty = exampleProperty;
}
}
static class ExampleDefaultsBean {
private int foo = 123;

19
spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/KotlinConfigurationPropertiesTests.kt

@ -26,11 +26,13 @@ import org.springframework.context.annotation.Import @@ -26,11 +26,13 @@ import org.springframework.context.annotation.Import
import org.springframework.test.context.support.TestPropertySourceUtils
import org.assertj.core.api.Assertions.assertThat
import org.springframework.boot.context.properties.bind.Name
/**
* Tests for {@link ConfigurationProperties @ConfigurationProperties}-annotated beans.
*
* @author Madhura Bhave
* @author Lasse Wulff
*/
class KotlinConfigurationPropertiesTests {
@ -59,6 +61,14 @@ class KotlinConfigurationPropertiesTests { @@ -59,6 +61,14 @@ class KotlinConfigurationPropertiesTests {
assertThat(this.context.getBean(LateInitProperties::class.java).inner.value).isEqualTo("alpha")
}
@Test
fun `renamed property can be bound to late init attribute`() {
this.context.register(EnableRenamedLateInitProperties::class.java)
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, "renamed.var=beta")
this.context.refresh()
assertThat(this.context.getBean(RenamedLateInitProperties::class.java).bar).isEqualTo("beta")
}
@Test
fun `type with constructor bound lateinit property with default can be bound`() {
this.context.register(EnableLateInitPropertiesWithDefault::class.java)
@ -80,6 +90,15 @@ class KotlinConfigurationPropertiesTests { @@ -80,6 +90,15 @@ class KotlinConfigurationPropertiesTests {
@ConfigurationProperties(prefix = "foo")
class BingProperties(@Suppress("UNUSED_PARAMETER") bar: String)
@ConfigurationProperties(prefix = "renamed")
class RenamedLateInitProperties{
@Name("var")
lateinit var bar: String
}
@EnableConfigurationProperties(RenamedLateInitProperties::class)
class EnableRenamedLateInitProperties
@EnableConfigurationProperties
class EnableConfigProperties

Loading…
Cancel
Save