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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -254,7 +254,34 @@ public class ConfigurationClassPostProcessorTests {
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
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 {
|
||||
|
||||
@Bean
|
||||
public Repository repo() {
|
||||
public Repository rawRepo() {
|
||||
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();
|
||||
for (ResolvableType generic : generics) {
|
||||
if (generic.isUnresolvableTypeVariable()) {
|
||||
if (generic.isUnresolvableTypeVariable() || generic.isWildcardWithoutBounds()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -435,6 +435,23 @@ public final class ResolvableType implements Serializable {
|
||||
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
|
||||
* {@link #getNested(int, Map)} for details.
|
||||
|
||||
Reference in New Issue
Block a user