Skip to content

Commit a605f07

Browse files
committed
Merge branch '6.2.x'
# Conflicts: # spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java
2 parents 5a0848b + 2472126 commit a605f07

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,15 @@ public AutowireCandidateResolver cloneIfNecessary() {
6666
* @see org.springframework.beans.factory.config.BeanDefinition#isAutowireCandidate()
6767
* @see AbstractBeanDefinition#isDefaultCandidate()
6868
*/
69+
@SuppressWarnings("unchecked")
6970
public static <T> Map<String, T> resolveAutowireCandidates(ConfigurableListableBeanFactory lbf, Class<T> type) {
7071
Map<String, T> candidates = new LinkedHashMap<>();
7172
for (String beanName : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(lbf, type)) {
7273
if (AutowireUtils.isAutowireCandidate(lbf, beanName)) {
73-
candidates.put(beanName, lbf.getBean(beanName, type));
74+
Object beanInstance = lbf.getBean(beanName);
75+
if (!(beanInstance instanceof NullBean)) {
76+
candidates.put(beanName, (T) beanInstance);
77+
}
7478
}
7579
}
7680
return candidates;

spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1770,6 +1770,10 @@ void objectProviderInjectionWithNonCandidatesInStream() {
17701770
parent.registerBeanDefinition("testBean4", tb4);
17711771
bf.setParentBeanFactory(parent);
17721772

1773+
RootBeanDefinition tb5 = new RootBeanDefinition(NullFactoryMethods.class);
1774+
tb5.setFactoryMethodName("createTestBean");
1775+
bf.registerBeanDefinition("testBean5", tb5);
1776+
17731777
ObjectProviderInjectionBean bean = bf.getBean("annotatedBean", ObjectProviderInjectionBean.class);
17741778
assertThat(bean.streamTestBeans()).containsExactly(bf.getBean("testBean1", TestBean.class),
17751779
bf.getBean("testBean2", TestBean.class));
@@ -1789,7 +1793,7 @@ void objectProviderInjectionWithNonCandidatesInStream() {
17891793
Map<String, TestBean> typeMatches = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, TestBean.class);
17901794
assertThat(typeMatches.remove("testBean3")).isNotNull();
17911795
Map<String, TestBean> candidates = SimpleAutowireCandidateResolver.resolveAutowireCandidates(bf, TestBean.class);
1792-
assertThat(candidates).containsExactlyEntriesOf(candidates);
1796+
assertThat(candidates).containsExactlyEntriesOf(typeMatches);
17931797
}
17941798

17951799
@Test

spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,13 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
341341
conditionalConverter.matches(sourceType, targetType);
342342
}
343343

344+
public boolean matchesFallback(TypeDescriptor sourceType, TypeDescriptor targetType) {
345+
return (this.typeInfo.getTargetType() == targetType.getObjectType() &&
346+
this.targetType.hasUnresolvableGenerics() &&
347+
(!(this.converter instanceof ConditionalConverter conditionalConverter) ||
348+
conditionalConverter.matches(sourceType, targetType)));
349+
}
350+
344351
@Override
345352
public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
346353
if (source == null) {
@@ -610,12 +617,20 @@ public void add(GenericConverter converter) {
610617
}
611618

612619
public @Nullable GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
620+
// Look for proper match among all converters (taking full generics into account)
613621
for (GenericConverter converter : this.converters) {
614622
if (!(converter instanceof ConditionalGenericConverter genericConverter) ||
615623
genericConverter.matches(sourceType, targetType)) {
616624
return converter;
617625
}
618626
}
627+
// Fallback to pre-6.2.3 behavior: accept Class match for unresolvable generics
628+
for (GenericConverter converter : this.converters) {
629+
if (converter instanceof ConverterAdapter converterAdapter &&
630+
converterAdapter.matchesFallback(sourceType, targetType)) {
631+
return converter;
632+
}
633+
}
619634
return null;
620635
}
621636

spring-core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,18 @@ void stringListToListOfSubclassOfUnboundGenericClass() {
581581
assertThat(bList).allMatch(e -> e instanceof BRaw);
582582
}
583583

584+
@Test
585+
void stringToListOfMapConverterWithFallbackMatch() {
586+
conversionService.addConverter(new StringToListOfMapConverter());
587+
588+
List<Map<String, Object>> result = (List<Map<String, Object>>) conversionService.convert("foo",
589+
TypeDescriptor.valueOf(String.class),
590+
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Map.class))
591+
);
592+
593+
assertThat("foo").isEqualTo(result.get(0).get("bar"));
594+
}
595+
584596

585597
@ExampleAnnotation(active = true)
586598
public String annotatedString;
@@ -969,4 +981,13 @@ public List<BRaw> convert(List<String> source) {
969981
}
970982
}
971983

984+
985+
private static class StringToListOfMapConverter implements Converter<String, List<? extends Map<String, ?>>> {
986+
987+
@Override
988+
public List<? extends Map<String, ?>> convert(String source) {
989+
return List.of(Map.of("bar", source));
990+
}
991+
}
992+
972993
}

0 commit comments

Comments
 (0)