Consider wildcard type without bounds as eligible for fallback match too
Issue: SPR-11250
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -254,7 +254,34 @@ public class ConfigurationClassPostProcessorTests {
|
|||||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||||
pp.postProcessBeanFactory(beanFactory);
|
pp.postProcessBeanFactory(beanFactory);
|
||||||
|
|
||||||
assertSame(beanFactory.getBean("repo"), beanFactory.getBean("repoConsumer"));
|
assertSame(beanFactory.getBean("rawRepo"), beanFactory.getBean("repoConsumer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenericsBasedInjectionWithWildcardMatch() {
|
||||||
|
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardMatchingConfiguration.class));
|
||||||
|
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||||
|
pp.postProcessBeanFactory(beanFactory);
|
||||||
|
|
||||||
|
assertSame(beanFactory.getBean("genericRepo"), beanFactory.getBean("repoConsumer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenericsBasedInjectionWithWildcardWithExtendsMatch() {
|
||||||
|
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardWithExtendsConfiguration.class));
|
||||||
|
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||||
|
pp.postProcessBeanFactory(beanFactory);
|
||||||
|
|
||||||
|
assertSame(beanFactory.getBean("stringRepo"), beanFactory.getBean("repoConsumer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenericsBasedInjectionWithWildcardWithGenericExtendsMatch() {
|
||||||
|
beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardWithGenericExtendsConfiguration.class));
|
||||||
|
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||||
|
pp.postProcessBeanFactory(beanFactory);
|
||||||
|
|
||||||
|
assertSame(beanFactory.getBean("genericRepo"), beanFactory.getBean("repoConsumer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -362,6 +389,16 @@ public class ConfigurationClassPostProcessorTests {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Repository<?> genericRepo() {
|
||||||
|
return new Repository<Object>() {
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Repository<Object>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -387,6 +424,16 @@ public class ConfigurationClassPostProcessorTests {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean @Scope("prototype")
|
||||||
|
public Repository genericRepo() {
|
||||||
|
return new Repository<Object>() {
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Repository<Object>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -461,7 +508,7 @@ public class ConfigurationClassPostProcessorTests {
|
|||||||
public static class RawMatchingConfiguration {
|
public static class RawMatchingConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Repository repo() {
|
public Repository rawRepo() {
|
||||||
return new Repository();
|
return new Repository();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,4 +518,59 @@ public class ConfigurationClassPostProcessorTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public static class WildcardMatchingConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Repository<?> genericRepo() {
|
||||||
|
return new Repository();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Object repoConsumer(Repository<String> repo) {
|
||||||
|
return repo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public static class WildcardWithExtendsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Repository<? extends String> stringRepo() {
|
||||||
|
return new Repository<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Repository<? extends Number> numberRepo() {
|
||||||
|
return new Repository<Number>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Object repoConsumer(Repository<? extends String> repo) {
|
||||||
|
return repo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public static class WildcardWithGenericExtendsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Repository<? extends Object> genericRepo() {
|
||||||
|
return new Repository<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Repository<? extends Number> numberRepo() {
|
||||||
|
return new Repository<Number>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Object repoConsumer(Repository<String> repo) {
|
||||||
|
return repo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -399,7 +399,7 @@ public final class ResolvableType implements Serializable {
|
|||||||
}
|
}
|
||||||
ResolvableType[] generics = getGenerics();
|
ResolvableType[] generics = getGenerics();
|
||||||
for (ResolvableType generic : generics) {
|
for (ResolvableType generic : generics) {
|
||||||
if (generic.isUnresolvableTypeVariable()) {
|
if (generic.isUnresolvableTypeVariable() || generic.isWildcardWithoutBounds()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,6 +435,23 @@ public final class ResolvableType implements Serializable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the underlying type represents a wildcard
|
||||||
|
* without specific bounds (i.e., equal to {@code ? extends Object}).
|
||||||
|
*/
|
||||||
|
private boolean isWildcardWithoutBounds() {
|
||||||
|
if (this.type instanceof WildcardType) {
|
||||||
|
WildcardType wt = (WildcardType) this.type;
|
||||||
|
if (wt.getLowerBounds().length == 0) {
|
||||||
|
Type[] upperBounds = wt.getUpperBounds();
|
||||||
|
if (upperBounds.length == 0 || (upperBounds.length == 1 && Object.class.equals(upperBounds[0]))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a {@link ResolvableType} for the specified nesting level. See
|
* Return a {@link ResolvableType} for the specified nesting level. See
|
||||||
* {@link #getNested(int, Map)} for details.
|
* {@link #getNested(int, Map)} for details.
|
||||||
|
|||||||
Reference in New Issue
Block a user