Skip to content

Commit a4e84c2

Browse files
committed
Revert "Fix nested type discovery in ConfigurationPropertiesReflectionHintsProcessor"
This reverts commit 7855888.
1 parent 1aadc2a commit a4e84c2

File tree

3 files changed

+347
-458
lines changed

3 files changed

+347
-458
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesReflectionHintsProcessor.java

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.beans.Introspector;
2222
import java.beans.PropertyDescriptor;
2323
import java.lang.reflect.Constructor;
24+
import java.lang.reflect.Field;
2425
import java.lang.reflect.Method;
2526
import java.util.Arrays;
2627
import java.util.Collection;
@@ -34,10 +35,12 @@
3435
import org.springframework.beans.ExtendedBeanInfoFactory;
3536
import org.springframework.boot.context.properties.bind.Bindable;
3637
import org.springframework.core.ResolvableType;
38+
import org.springframework.core.annotation.MergedAnnotations;
39+
import org.springframework.util.ReflectionUtils;
3740

3841
/**
3942
* Registers a given type on {@link ReflectionHints} for binding purposes, discovering any
40-
* referenced types it may expose via a property.
43+
* nested type it may expose via a property.
4144
*
4245
* @author Andy Wilkinson
4346
* @author Moritz Halbritter
@@ -74,22 +77,12 @@ public static void processConfigurationProperties(Class<?> type, ReflectionHints
7477
.process(reflectionHints);
7578
}
7679

77-
private void processType(Class<?> type, ReflectionHints reflectionHints) {
78-
if (isTypeIgnored(type)) {
79-
return;
80-
}
81-
new ConfigurationPropertiesReflectionHintsProcessor(type, getBindConstructor(type, true), this.seen)
82-
.process(reflectionHints);
80+
private void processNestedType(Class<?> type, ReflectionHints reflectionHints) {
81+
processNestedType(type, getBindConstructor(type, true), reflectionHints);
8382
}
8483

85-
private boolean isTypeIgnored(Class<?> type) {
86-
if (type.getPackageName().startsWith("java.")) {
87-
return true;
88-
}
89-
if (type.isInterface()) {
90-
return true;
91-
}
92-
return false;
84+
private void processNestedType(Class<?> type, Constructor<?> bindConstructor, ReflectionHints reflectionHints) {
85+
new ConfigurationPropertiesReflectionHintsProcessor(type, bindConstructor, this.seen).process(reflectionHints);
9386
}
9487

9588
private static Constructor<?> getBindConstructor(Class<?> type, boolean nestedType) {
@@ -125,8 +118,9 @@ private void handleConstructor(ReflectionHints reflectionHints) {
125118

126119
private void handleValueObjectProperties(ReflectionHints reflectionHints) {
127120
for (int i = 0; i < this.bindConstructor.getParameterCount(); i++) {
121+
String propertyName = this.bindConstructor.getParameters()[i].getName();
128122
ResolvableType propertyType = ResolvableType.forConstructorParameter(this.bindConstructor, i);
129-
registerType(reflectionHints, propertyType);
123+
handleProperty(reflectionHints, propertyName, propertyType);
130124
}
131125
}
132126

@@ -135,12 +129,16 @@ private void handleJavaBeanProperties(ReflectionHints reflectionHints) {
135129
Method readMethod = propertyDescriptor.getReadMethod();
136130
if (readMethod != null) {
137131
ResolvableType propertyType = ResolvableType.forMethodReturnType(readMethod, this.type);
138-
registerType(reflectionHints, propertyType);
132+
String propertyName = propertyDescriptor.getName();
133+
if (isSetterMandatory(propertyName, propertyType) && propertyDescriptor.getWriteMethod() == null) {
134+
continue;
135+
}
136+
handleProperty(reflectionHints, propertyName, propertyType);
139137
}
140138
}
141139
}
142140

143-
private void registerType(ReflectionHints reflectionHints, ResolvableType propertyType) {
141+
private void handleProperty(ReflectionHints reflectionHints, String propertyName, ResolvableType propertyType) {
144142
Class<?> propertyClass = propertyType.resolve();
145143
if (propertyClass == null) {
146144
return;
@@ -150,11 +148,25 @@ private void registerType(ReflectionHints reflectionHints, ResolvableType proper
150148
}
151149
Class<?> componentType = getComponentType(propertyType);
152150
if (componentType != null) {
153-
processType(componentType, reflectionHints);
151+
// Can be a list of simple types
152+
if (!isJavaType(componentType)) {
153+
processNestedType(componentType, reflectionHints);
154+
}
154155
}
155-
else {
156-
processType(propertyClass, reflectionHints);
156+
else if (isNestedType(propertyName, propertyClass)) {
157+
processNestedType(propertyClass, reflectionHints);
158+
}
159+
}
160+
161+
private boolean isSetterMandatory(String propertyName, ResolvableType propertyType) {
162+
Class<?> propertyClass = propertyType.resolve();
163+
if (propertyClass == null) {
164+
return true;
157165
}
166+
if (getComponentType(propertyType) != null) {
167+
return false;
168+
}
169+
return !isNestedType(propertyName, propertyClass);
158170
}
159171

160172
private Class<?> getComponentType(ResolvableType propertyType) {
@@ -171,6 +183,27 @@ else if (Map.class.isAssignableFrom(propertyClass)) {
171183
return null;
172184
}
173185

186+
/**
187+
* Specify whether the specified property refer to a nested type. A nested type
188+
* represents a sub-namespace that need to be fully resolved.
189+
* @param propertyName the name of the property
190+
* @param propertyType the type of the property
191+
* @return whether the specified {@code propertyType} is a nested type
192+
*/
193+
private boolean isNestedType(String propertyName, Class<?> propertyType) {
194+
if (this.type.equals(propertyType.getDeclaringClass())) {
195+
return true;
196+
}
197+
else {
198+
Field field = ReflectionUtils.findField(this.type, propertyName);
199+
return field != null && MergedAnnotations.from(field).isPresent(NestedConfigurationProperty.class);
200+
}
201+
}
202+
203+
private boolean isJavaType(Class<?> candidate) {
204+
return candidate.getPackageName().startsWith("java.");
205+
}
206+
174207
private static BeanInfo getBeanInfo(Class<?> beanType) {
175208
try {
176209
BeanInfo beanInfo = beanInfoFactory.getBeanInfo(beanType);

0 commit comments

Comments
 (0)