mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Add possibility for mapping a property to an attribute with different name
Makes the Name annotation applicable on fields and takes this name when looking up the corresponding property. See gh-37105
This commit is contained in:
parent
500584f052
commit
2c1aced25f
|
@ -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 {
|
|||
|
||||
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 {
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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,27 @@ 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 bindRenamedPropertyToRecordBean() {
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
source.put("renamed.class", "alpha");
|
||||
this.sources.add(source);
|
||||
ExampleRenamedPropertyRecordBean bean = this.binder
|
||||
.bind("renamed", Bindable.of(ExampleRenamedPropertyRecordBean.class))
|
||||
.get();
|
||||
assertThat(bean.exampleProperty()).isEqualTo("alpha");
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindToClassWhenHasNoPrefixShouldCreateBoundBean() {
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
|
@ -648,6 +670,24 @@ class JavaBeanBinderTests {
|
|||
|
||||
}
|
||||
|
||||
static class ExampleRenamedPropertyBean {
|
||||
|
||||
@Name("public")
|
||||
private String exampleProperty;
|
||||
|
||||
String getExampleProperty() {
|
||||
return this.exampleProperty;
|
||||
}
|
||||
|
||||
void setExampleProperty(String exampleProperty) {
|
||||
this.exampleProperty = exampleProperty;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
record ExampleRenamedPropertyRecordBean(@Name("class") String exampleProperty) {
|
||||
}
|
||||
|
||||
static class ExampleDefaultsBean {
|
||||
|
||||
private int foo = 123;
|
||||
|
|
|
@ -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,22 @@ class KotlinConfigurationPropertiesTests {
|
|||
assertThat(this.context.getBean(LateInitProperties::class.java).inner.value).isEqualTo("alpha")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `renamed property can be bound`() {
|
||||
this.context.register(EnableRenamedProperties::class.java)
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, "renamed.fun=beta")
|
||||
this.context.refresh()
|
||||
assertThat(this.context.getBean(RenamedProperties::class.java).bar).isEqualTo("beta")
|
||||
}
|
||||
|
||||
@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 +98,21 @@ class KotlinConfigurationPropertiesTests {
|
|||
@ConfigurationProperties(prefix = "foo")
|
||||
class BingProperties(@Suppress("UNUSED_PARAMETER") bar: String)
|
||||
|
||||
@ConfigurationProperties(prefix = "renamed")
|
||||
class RenamedProperties(@Name("fun") val bar: String)
|
||||
|
||||
@EnableConfigurationProperties(RenamedProperties::class)
|
||||
class EnableRenamedProperties
|
||||
|
||||
@ConfigurationProperties(prefix = "renamed")
|
||||
class RenamedLateInitProperties{
|
||||
@Name("var")
|
||||
lateinit var bar: String
|
||||
}
|
||||
|
||||
@EnableConfigurationProperties(RenamedLateInitProperties::class)
|
||||
class EnableRenamedLateInitProperties
|
||||
|
||||
@EnableConfigurationProperties
|
||||
class EnableConfigProperties
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user