diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java index 3e5dd904245a..57a12e331bcb 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. @@ -17,6 +17,7 @@ package org.springframework.boot.actuate.context.properties; import java.lang.reflect.Constructor; +import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -58,12 +59,16 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationPropertiesBean; import org.springframework.boot.context.properties.ConstructorBinding; +import org.springframework.boot.context.properties.bind.Name; import org.springframework.boot.context.properties.source.ConfigurationProperty; import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.boot.origin.Origin; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.KotlinDetector; +import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.core.annotation.MergedAnnotations.SearchStrategy; import org.springframework.util.ClassUtils; @@ -384,6 +389,8 @@ public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider */ protected static class GenericSerializerModifier extends BeanSerializerModifier { + private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); + @Override public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) { @@ -398,11 +405,21 @@ public List changeProperties(SerializationConfig config, Bea return result; } - private boolean isCandidate(BeanDescription beanDesc, BeanPropertyWriter writer, - Constructor bindConstructor) { - if (bindConstructor != null) { - return Arrays.stream(bindConstructor.getParameters()) - .anyMatch((parameter) -> parameter.getName().equals(writer.getName())); + private boolean isCandidate(BeanDescription beanDesc, BeanPropertyWriter writer, Constructor constructor) { + if (constructor != null) { + Parameter[] parameters = constructor.getParameters(); + String[] names = PARAMETER_NAME_DISCOVERER.getParameterNames(constructor); + if (names == null) { + names = new String[parameters.length]; + } + for (int i = 0; i < parameters.length; i++) { + String name = MergedAnnotations.from(parameters[i]).get(Name.class) + .getValue(MergedAnnotation.VALUE, String.class) + .orElse((names[i] != null) ? names[i] : parameters[i].getName()); + if (name.equals(writer.getName())) { + return true; + } + } } return isReadable(beanDesc, writer); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java index 0533ca00d68e..163d252c53d1 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. @@ -34,6 +34,7 @@ import org.springframework.boot.context.properties.ConstructorBinding; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.bind.DefaultValue; +import org.springframework.boot.context.properties.bind.Name; import org.springframework.boot.origin.Origin; import org.springframework.boot.origin.OriginLookup; import org.springframework.boot.test.context.assertj.AssertableApplicationContext; @@ -73,7 +74,7 @@ void descriptorWithJavaBeanBindMethodDetectsRelevantProperties() { void descriptorWithValueObjectBindMethodDetectsRelevantProperties() { this.contextRunner.withUserConfiguration(ImmutablePropertiesConfiguration.class).run(assertProperties( "immutable", - (properties) -> assertThat(properties).containsOnlyKeys("dbPassword", "myTestProperty", "duration"))); + (properties) -> assertThat(properties).containsOnlyKeys("dbPassword", "myTestProperty", "for"))); } @Test @@ -451,16 +452,16 @@ public static class ImmutableProperties { private final String nullValue; - private final Duration duration; + private final Duration forDuration; private final String ignored; ImmutableProperties(@DefaultValue("123456") String dbPassword, @DefaultValue("654321") String myTestProperty, - String nullValue, @DefaultValue("10s") Duration duration) { + String nullValue, @DefaultValue("10s") @Name("for") Duration forDuration) { this.dbPassword = dbPassword; this.myTestProperty = myTestProperty; this.nullValue = nullValue; - this.duration = duration; + this.forDuration = forDuration; this.ignored = "dummy"; } @@ -476,8 +477,8 @@ public String getNullValue() { return this.nullValue; } - public Duration getDuration() { - return this.duration; + public Duration getFor() { + return this.forDuration; } public String getIgnored() {