Browse Source

Consider wildcard type without bounds as eligible for fallback match too

Issue: SPR-11250
pull/443/merge
Juergen Hoeller 12 years ago
parent
commit
709ac28f29
  1. 108
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java
  2. 19
      spring-core/src/main/java/org/springframework/core/ResolvableType.java

108
spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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,22 @@ public class ConfigurationClassPostProcessorTests { @@ -461,7 +508,22 @@ public class ConfigurationClassPostProcessorTests {
public static class RawMatchingConfiguration {
@Bean
public Repository repo() {
public Repository rawRepo() {
return new Repository();
}
@Bean
public Object repoConsumer(Repository<String> repo) {
return repo;
}
}
@Configuration
public static class WildcardMatchingConfiguration {
@Bean
public Repository<?> genericRepo() {
return new Repository();
}
@ -471,4 +533,44 @@ public class ConfigurationClassPostProcessorTests { @@ -471,4 +533,44 @@ public class ConfigurationClassPostProcessorTests {
}
}
@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;
}
}
}

19
spring-core/src/main/java/org/springframework/core/ResolvableType.java

@ -399,7 +399,7 @@ public final class ResolvableType implements Serializable { @@ -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 { @@ -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.

Loading…
Cancel
Save