Skip to content
This repository was archived by the owner on Feb 23, 2023. It is now read-only.

Commit b264eae

Browse files
committed
Polish "Fix StackOverflowError when processing ConfigurationProperties"
See gh-1420
1 parent f4992ff commit b264eae

File tree

2 files changed

+30
-13
lines changed

2 files changed

+30
-13
lines changed

spring-aot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesNativeConfigurationProcessor.java

+24-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2021 the original author or authors.
2+
* Copyright 2019-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,8 +26,10 @@
2626
import java.lang.reflect.Method;
2727
import java.util.Arrays;
2828
import java.util.Collection;
29+
import java.util.HashSet;
2930
import java.util.List;
3031
import java.util.Map;
32+
import java.util.Set;
3133
import java.util.stream.Collectors;
3234

3335
import org.springframework.aot.context.bootstrap.generator.infrastructure.nativex.BeanFactoryNativeConfigurationProcessor;
@@ -67,7 +69,7 @@ public void process(ConfigurableListableBeanFactory beanFactory, NativeConfigura
6769

6870
private void processConfigurationProperties(NativeConfigurationRegistry registry, BeanDefinition beanDefinition) {
6971
Class<?> type = ClassUtils.getUserClass(beanDefinition.getResolvableType().toClass());
70-
TypeProcessor.process(type, registry);
72+
TypeProcessor.processConfigurationProperties(type, registry);
7173
}
7274

7375
/**
@@ -84,24 +86,36 @@ private static class TypeProcessor {
8486

8587
private final BeanInfo beanInfo;
8688

87-
private TypeProcessor(Class<?> type, boolean constructorBinding) {
89+
private final Set<Class<?>> seen;
90+
91+
private TypeProcessor(Class<?> type, boolean constructorBinding, Set<Class<?>> seen) {
8892
this.type = type;
8993
this.constructorBinding = constructorBinding;
9094
this.beanInfo = getBeanInfo(type);
95+
this.seen = seen;
96+
}
97+
98+
public static void processConfigurationProperties(Class<?> type, NativeConfigurationRegistry registry) {
99+
new TypeProcessor(type, hasConstructorBinding(type), new HashSet<>()).process(registry);
100+
}
101+
102+
private void processNestedType(Class<?> type, NativeConfigurationRegistry registry) {
103+
processNestedType(type, hasConstructorBinding(type), registry);
91104
}
92105

93-
public static void process(Class<?> type, NativeConfigurationRegistry registry) {
94-
new TypeProcessor(type, hasConstructorBinding(type)).process(registry);
106+
private void processNestedType(Class<?> type, boolean constructorBinding, NativeConfigurationRegistry registry) {
107+
new TypeProcessor(type, constructorBinding, this.seen).process(registry);
95108
}
96109

97110
private static boolean hasConstructorBinding(AnnotatedElement element) {
98111
return MergedAnnotations.from(element).isPresent(ConstructorBinding.class);
99112
}
100113

101114
private void process(NativeConfigurationRegistry registry) {
102-
if (registry.reflection().reflectionEntries().anyMatch(x -> x.getType() == this.type)) {
115+
if (this.seen.contains(this.type)) {
103116
return;
104117
}
118+
this.seen.add(this.type);
105119
Builder reflection = registry.reflection().forType(this.type);
106120
if (isClassOnlyReflectionType()) {
107121
return;
@@ -142,10 +156,10 @@ private void handleValueObjectProperties(NativeConfigurationRegistry registry, C
142156
if (propertyClass.equals(beanInfo.getBeanDescriptor().getBeanClass())) {
143157
return; // Prevent infinite recursion
144158
}
145-
new TypeProcessor(propertyType.resolve(), true).process(registry);
159+
processNestedType(propertyType.resolve(), true, registry);
146160
Class<?> nestedType = getNestedType(constructor.getParameters()[i].getName(), propertyType);
147161
if (nestedType != null) {
148-
new TypeProcessor(nestedType, true).process(registry);
162+
processNestedType(nestedType, true, registry);
149163
}
150164
}
151165
}
@@ -159,10 +173,10 @@ private void handleJavaBeanProperties(NativeConfigurationRegistry registry) {
159173
if (propertyClass.equals(beanInfo.getBeanDescriptor().getBeanClass())) {
160174
return; // Prevent infinite recursion
161175
}
162-
TypeProcessor.process(propertyClass, registry);
176+
processNestedType(propertyClass, registry);
163177
Class<?> nestedType = getNestedType(propertyDescriptor.getName(), propertyType);
164178
if (nestedType != null) {
165-
TypeProcessor.process(nestedType, registry);
179+
processNestedType(nestedType, registry);
166180
}
167181
}
168182
}

spring-aot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesNativeConfigurationProcessorTests.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2021 the original author or authors.
2+
* Copyright 2019-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -534,8 +534,7 @@ public ImmutableRecursive(ImmutableRecursive recursive) {
534534

535535
}
536536

537-
538-
@ConfigurationProperties("crossReference")
537+
@ConfigurationProperties("crossreference")
539538
static class SamplePropertiesWithCrossReference {
540539

541540
@NestedConfigurationProperty
@@ -551,6 +550,7 @@ public CrossReferenceA getCrossReferenceA() {
551550
}
552551

553552
static class CrossReferenceA {
553+
554554
private CrossReferenceB crossReferenceB;
555555

556556
public void setCrossReferenceB(CrossReferenceB crossReferenceB) {
@@ -560,9 +560,11 @@ public void setCrossReferenceB(CrossReferenceB crossReferenceB) {
560560
public CrossReferenceB getCrossReferenceB() {
561561
return crossReferenceB;
562562
}
563+
563564
}
564565

565566
static class CrossReferenceB {
567+
566568
private CrossReferenceA crossReferenceA;
567569

568570
public void setCrossReferenceA(CrossReferenceA crossReferenceA) {
@@ -572,6 +574,7 @@ public void setCrossReferenceA(CrossReferenceA crossReferenceA) {
572574
public CrossReferenceA getCrossReferenceA() {
573575
return crossReferenceA;
574576
}
577+
575578
}
576579

577580
}

0 commit comments

Comments
 (0)