Consistent support for generic FactoryBean type matching
Closes gh-32590 See gh-32489
This commit is contained in:
		
							parent
							
								
									802967fc98
								
							
						
					
					
						commit
						f2889b1b43
					
				|  | @ -525,16 +525,46 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp | ||||||
| 		// Check manually registered singletons. | 		// Check manually registered singletons. | ||||||
| 		Object beanInstance = getSingleton(beanName, false); | 		Object beanInstance = getSingleton(beanName, false); | ||||||
| 		if (beanInstance != null && beanInstance.getClass() != NullBean.class) { | 		if (beanInstance != null && beanInstance.getClass() != NullBean.class) { | ||||||
|  | 
 | ||||||
|  | 			// Determine target for FactoryBean match if necessary. | ||||||
| 			if (beanInstance instanceof FactoryBean<?> factoryBean) { | 			if (beanInstance instanceof FactoryBean<?> factoryBean) { | ||||||
| 				if (!isFactoryDereference) { | 				if (!isFactoryDereference) { | ||||||
| 					Class<?> type = getTypeForFactoryBean(factoryBean); | 					Class<?> type = getTypeForFactoryBean(factoryBean); | ||||||
| 					return (type != null && typeToMatch.isAssignableFrom(type)); | 					if (type == null) { | ||||||
|  | 						return false; | ||||||
|  | 					} | ||||||
|  | 					if (typeToMatch.isAssignableFrom(type)) { | ||||||
|  | 						return true; | ||||||
|  | 					} | ||||||
|  | 					else if (typeToMatch.hasGenerics() && containsBeanDefinition(beanName)) { | ||||||
|  | 						RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); | ||||||
|  | 						ResolvableType targetType = mbd.targetType; | ||||||
|  | 						if (targetType == null) { | ||||||
|  | 							targetType = mbd.factoryMethodReturnType; | ||||||
|  | 						} | ||||||
|  | 						if (targetType == null) { | ||||||
|  | 							return false; | ||||||
|  | 						} | ||||||
|  | 						Class<?> targetClass = targetType.resolve(); | ||||||
|  | 						if (targetClass != null && FactoryBean.class.isAssignableFrom(targetClass)) { | ||||||
|  | 							Class<?> classToMatch = typeToMatch.resolve(); | ||||||
|  | 							if (classToMatch != null && !FactoryBean.class.isAssignableFrom(classToMatch) && | ||||||
|  | 									!classToMatch.isAssignableFrom(targetType.toClass())) { | ||||||
|  | 								return typeToMatch.isAssignableFrom(targetType.getGeneric()); | ||||||
|  | 							} | ||||||
| 						} | 						} | ||||||
| 						else { | 						else { | ||||||
| 					return typeToMatch.isInstance(beanInstance); | 							return typeToMatch.isAssignableFrom(targetType); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 			else if (!isFactoryDereference) { | 					return false; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else if (isFactoryDereference) { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Actual matching against bean instance... | ||||||
| 			if (typeToMatch.isInstance(beanInstance)) { | 			if (typeToMatch.isInstance(beanInstance)) { | ||||||
| 				// Direct match for exposed instance? | 				// Direct match for exposed instance? | ||||||
| 				return true; | 				return true; | ||||||
|  | @ -559,9 +589,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp | ||||||
| 				} | 				} | ||||||
| 				return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType)); | 				return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType)); | ||||||
| 			} | 			} | ||||||
| 			} | 			else { | ||||||
| 				return false; | 				return false; | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 		else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) { | 		else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) { | ||||||
| 			// null instance registered | 			// null instance registered | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
|  | @ -102,23 +102,6 @@ public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCan | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else { |  | ||||||
| 				// Pre-existing target type: In case of a generic FactoryBean type, |  | ||||||
| 				// unwrap nested generic type when matching a non-FactoryBean type. |  | ||||||
| 				Class<?> resolvedClass = targetType.resolve(); |  | ||||||
| 				if (resolvedClass != null && FactoryBean.class.isAssignableFrom(resolvedClass)) { |  | ||||||
| 					Class<?> typeToBeMatched = dependencyType.resolve(); |  | ||||||
| 					if (typeToBeMatched != null && !FactoryBean.class.isAssignableFrom(typeToBeMatched) && |  | ||||||
| 							!typeToBeMatched.isAssignableFrom(resolvedClass)) { |  | ||||||
| 						targetType = targetType.getGeneric(); |  | ||||||
| 						if (descriptor.fallbackMatchAllowed()) { |  | ||||||
| 							// Matching the Class-based type determination for FactoryBean |  | ||||||
| 							// objects in the lazy-determination getType code path below. |  | ||||||
| 							targetType = ResolvableType.forClass(targetType.resolve()); |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (targetType == null) { | 		if (targetType == null) { | ||||||
|  | @ -145,6 +128,23 @@ public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCan | ||||||
| 		if (cacheType) { | 		if (cacheType) { | ||||||
| 			rbd.targetType = targetType; | 			rbd.targetType = targetType; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		// Pre-declared target type: In case of a generic FactoryBean type, | ||||||
|  | 		// unwrap nested generic type when matching a non-FactoryBean type. | ||||||
|  | 		Class<?> targetClass = targetType.resolve(); | ||||||
|  | 		if (targetClass != null && FactoryBean.class.isAssignableFrom(targetClass)) { | ||||||
|  | 			Class<?> classToMatch = dependencyType.resolve(); | ||||||
|  | 			if (classToMatch != null && !FactoryBean.class.isAssignableFrom(classToMatch) && | ||||||
|  | 					!classToMatch.isAssignableFrom(targetClass)) { | ||||||
|  | 				targetType = targetType.getGeneric(); | ||||||
|  | 				if (descriptor.fallbackMatchAllowed()) { | ||||||
|  | 					// Matching the Class-based type determination for FactoryBean | ||||||
|  | 					// objects in the lazy-determination getType code path above. | ||||||
|  | 					targetType = ResolvableType.forClass(targetType.resolve()); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if (descriptor.fallbackMatchAllowed() && | 		if (descriptor.fallbackMatchAllowed() && | ||||||
| 				(targetType.hasUnresolvableGenerics() || targetType.resolve() == Properties.class)) { | 				(targetType.hasUnresolvableGenerics() || targetType.resolve() == Properties.class)) { | ||||||
| 			// Fallback matches allow unresolvable generics, e.g. plain HashMap to Map<String,String>; | 			// Fallback matches allow unresolvable generics, e.g. plain HashMap to Map<String,String>; | ||||||
|  |  | ||||||
|  | @ -29,6 +29,8 @@ import java.util.Map; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| 
 | 
 | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
| import org.mockito.Mockito; | import org.mockito.Mockito; | ||||||
| 
 | 
 | ||||||
| import org.springframework.beans.factory.BeanCreationException; | import org.springframework.beans.factory.BeanCreationException; | ||||||
|  | @ -64,27 +66,25 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericSetProperty() { | 	void genericSetProperty() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
| 		rbd.getPropertyValues().add("integerSet", Set.of("4", "5")); | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
|  | 		bd.getPropertyValues().add("integerSet", Set.of("4", "5")); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericListProperty() throws Exception { | 	void genericListProperty() throws Exception { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		List<String> input = List.of("http://localhost:8080", "http://localhost:9090"); | 		List<String> input = List.of("http://localhost:8080", "http://localhost:9090"); | ||||||
| 		rbd.getPropertyValues().add("resourceList", input); | 		bd.getPropertyValues().add("resourceList", input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getResourceList()) | 		assertThat(gb.getResourceList()) | ||||||
| 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | ||||||
| 	} | 	} | ||||||
|  | @ -95,11 +95,11 @@ class BeanFactoryGenericsTests { | ||||||
| 		bf.registerSingleton("resource1", new UrlResource("http://localhost:8080")); | 		bf.registerSingleton("resource1", new UrlResource("http://localhost:8080")); | ||||||
| 		bf.registerSingleton("resource2", new UrlResource("http://localhost:9090")); | 		bf.registerSingleton("resource2", new UrlResource("http://localhost:9090")); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericIntegerBean.class); | 		RootBeanDefinition bd = new RootBeanDefinition(GenericIntegerBean.class); | ||||||
| 		rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); | 		bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 		GenericIntegerBean gb = (GenericIntegerBean) bf.getBean("genericBean"); |  | ||||||
| 
 | 
 | ||||||
|  | 		GenericIntegerBean gb = (GenericIntegerBean) bf.getBean("genericBean"); | ||||||
| 		assertThat(gb.getResourceList()) | 		assertThat(gb.getResourceList()) | ||||||
| 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | ||||||
| 	} | 	} | ||||||
|  | @ -107,11 +107,11 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericListPropertyWithInvalidElementType() { | 	void genericListPropertyWithInvalidElementType() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericIntegerBean.class); |  | ||||||
| 
 | 
 | ||||||
| 		rbd.getPropertyValues().add("testBeanList", List.of(1)); | 		RootBeanDefinition bd = new RootBeanDefinition(GenericIntegerBean.class); | ||||||
|  | 		bd.getPropertyValues().add("testBeanList", List.of(1)); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> bf.getBean("genericBean")) | 		assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> bf.getBean("genericBean")) | ||||||
| 				.withMessageContaining("genericBean") | 				.withMessageContaining("genericBean") | ||||||
| 				.withMessageContaining("testBeanList[0]") | 				.withMessageContaining("testBeanList[0]") | ||||||
|  | @ -123,27 +123,26 @@ class BeanFactoryGenericsTests { | ||||||
| 	void genericListPropertyWithOptionalAutowiring() { | 	void genericListPropertyWithOptionalAutowiring() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); | 		bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); |  | ||||||
| 
 | 
 | ||||||
|  | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 		assertThat(gb.getResourceList()).isNull(); | 		assertThat(gb.getResourceList()).isNull(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapProperty() { | 	void genericMapProperty() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Map<String, String> input = Map.of( | 		Map<String, String> input = Map.of( | ||||||
| 				"4", "5", | 				"4", "5", | ||||||
| 				"6", "7"); | 				"6", "7"); | ||||||
| 		rbd.getPropertyValues().add("shortMap", input); | 		bd.getPropertyValues().add("shortMap", input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | ||||||
| 	} | 	} | ||||||
|  | @ -153,22 +152,21 @@ class BeanFactoryGenericsTests { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | ||||||
| 				new ClassPathResource("genericBeanTests.xml", getClass())); | 				new ClassPathResource("genericBeanTests.xml", getClass())); | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("listOfArrays"); |  | ||||||
| 
 | 
 | ||||||
|  | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("listOfArrays"); | ||||||
| 		assertThat(gb.getListOfArrays()).containsExactly(new String[] {"value1", "value2"}); | 		assertThat(gb.getListOfArrays()).containsExactly(new String[] {"value1", "value2"}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericSetConstructor() { | 	void genericSetConstructor() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Set<String> input = Set.of("4", "5"); | 		Set<String> input = Set.of("4", "5"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -178,11 +176,11 @@ class BeanFactoryGenericsTests { | ||||||
| 		bf.registerSingleton("integer1", 4); | 		bf.registerSingleton("integer1", 4); | ||||||
| 		bf.registerSingleton("integer2", 5); | 		bf.registerSingleton("integer2", 5); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); | 		bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); |  | ||||||
| 
 | 
 | ||||||
|  | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -190,27 +188,26 @@ class BeanFactoryGenericsTests { | ||||||
| 	void genericSetConstructorWithOptionalAutowiring() { | 	void genericSetConstructorWithOptionalAutowiring() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); | 		bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); |  | ||||||
| 
 | 
 | ||||||
|  | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 		assertThat(gb.getIntegerSet()).isNull(); | 		assertThat(gb.getIntegerSet()).isNull(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericSetListConstructor() throws Exception { | 	void genericSetListConstructor() throws Exception { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Set<String> input1 = Set.of("4", "5"); | 		Set<String> input1 = Set.of("4", "5"); | ||||||
| 		List<String> input2 = List.of("http://localhost:8080", "http://localhost:9090"); | 		List<String> input2 = List.of("http://localhost:8080", "http://localhost:9090"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input1); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input1); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input2); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input2); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | ||||||
| 		assertThat(gb.getResourceList()) | 		assertThat(gb.getResourceList()) | ||||||
| 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | ||||||
|  | @ -224,11 +221,11 @@ class BeanFactoryGenericsTests { | ||||||
| 		bf.registerSingleton("resource1", new UrlResource("http://localhost:8080")); | 		bf.registerSingleton("resource1", new UrlResource("http://localhost:8080")); | ||||||
| 		bf.registerSingleton("resource2", new UrlResource("http://localhost:9090")); | 		bf.registerSingleton("resource2", new UrlResource("http://localhost:9090")); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); | 		bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); |  | ||||||
| 
 | 
 | ||||||
|  | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | ||||||
| 		assertThat(gb.getResourceList()) | 		assertThat(gb.getResourceList()) | ||||||
| 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | ||||||
|  | @ -240,11 +237,11 @@ class BeanFactoryGenericsTests { | ||||||
| 		bf.registerSingleton("resource1", new UrlResource("http://localhost:8080")); | 		bf.registerSingleton("resource1", new UrlResource("http://localhost:8080")); | ||||||
| 		bf.registerSingleton("resource2", new UrlResource("http://localhost:9090")); | 		bf.registerSingleton("resource2", new UrlResource("http://localhost:9090")); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		rbd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); | 		bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); |  | ||||||
| 
 | 
 | ||||||
|  | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 		assertThat(gb.getIntegerSet()).isNull(); | 		assertThat(gb.getIntegerSet()).isNull(); | ||||||
| 		assertThat(gb.getResourceList()).isNull(); | 		assertThat(gb.getResourceList()).isNull(); | ||||||
| 	} | 	} | ||||||
|  | @ -252,18 +249,17 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericSetMapConstructor() { | 	void genericSetMapConstructor() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Set<String> input1 = Set.of("4", "5"); | 		Set<String> input1 = Set.of("4", "5"); | ||||||
| 		Map<String, String> input2 = Map.of( | 		Map<String, String> input2 = Map.of( | ||||||
| 				"4", "5", | 				"4", "5", | ||||||
| 				"6", "7"); | 				"6", "7"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input1); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input1); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input2); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input2); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | ||||||
|  | @ -272,17 +268,16 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapResourceConstructor() throws Exception { | 	void genericMapResourceConstructor() throws Exception { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Map<String, String> input = Map.of( | 		Map<String, String> input = Map.of( | ||||||
| 				"4", "5", | 				"4", "5", | ||||||
| 				"6", "7"); | 				"6", "7"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue("http://localhost:8080"); | 		bd.getConstructorArgumentValues().addGenericArgumentValue("http://localhost:8080"); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | ||||||
| 		assertThat(gb.getResourceList()).containsExactly(new UrlResource("http://localhost:8080")); | 		assertThat(gb.getResourceList()).containsExactly(new UrlResource("http://localhost:8080")); | ||||||
|  | @ -291,20 +286,19 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapMapConstructor() { | 	void genericMapMapConstructor() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Map<String, String> input1 = Map.of( | 		Map<String, String> input1 = Map.of( | ||||||
| 				"1", "0", | 				"1", "0", | ||||||
| 				"2", "3"); | 				"2", "3"); | ||||||
| 		Map<String, String> input2 = Map.of( | 		Map<String, String> input2 = Map.of( | ||||||
| 				"4", "5", | 				"4", "5", | ||||||
| 				"6", "7"); | 				"6", "7"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input1); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input1); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input2); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input2); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getShortMap()).isNotSameAs(gb.getPlainMap()); | 		assertThat(gb.getShortMap()).isNotSameAs(gb.getPlainMap()); | ||||||
| 		assertThat(gb.getPlainMap()).hasSize(2); | 		assertThat(gb.getPlainMap()).hasSize(2); | ||||||
| 		assertThat(gb.getPlainMap().get("1")).isEqualTo("0"); | 		assertThat(gb.getPlainMap().get("1")).isEqualTo("0"); | ||||||
|  | @ -317,17 +311,16 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapMapConstructorWithSameRefAndConversion() { | 	void genericMapMapConstructorWithSameRefAndConversion() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Map<String, String> input = Map.of( | 		Map<String, String> input = Map.of( | ||||||
| 				"1", "0", | 				"1", "0", | ||||||
| 				"2", "3"); | 				"2", "3"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getShortMap()).isNotSameAs(gb.getPlainMap()); | 		assertThat(gb.getShortMap()).isNotSameAs(gb.getPlainMap()); | ||||||
| 		assertThat(gb.getPlainMap()).hasSize(2); | 		assertThat(gb.getPlainMap()).hasSize(2); | ||||||
| 		assertThat(gb.getPlainMap().get("1")).isEqualTo("0"); | 		assertThat(gb.getPlainMap().get("1")).isEqualTo("0"); | ||||||
|  | @ -340,17 +333,16 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapMapConstructorWithSameRefAndNoConversion() { | 	void genericMapMapConstructorWithSameRefAndNoConversion() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Map<Short, Integer> input = new HashMap<>(); | 		Map<Short, Integer> input = new HashMap<>(); | ||||||
| 		input.put((short) 1, 0); | 		input.put((short) 1, 0); | ||||||
| 		input.put((short) 2, 3); | 		input.put((short) 2, 3); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getShortMap()).isSameAs(gb.getPlainMap()); | 		assertThat(gb.getShortMap()).isSameAs(gb.getPlainMap()); | ||||||
| 		assertThat(gb.getShortMap()).hasSize(2); | 		assertThat(gb.getShortMap()).hasSize(2); | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("1"))).isEqualTo(0); | 		assertThat(gb.getShortMap().get(Short.valueOf("1"))).isEqualTo(0); | ||||||
|  | @ -360,16 +352,15 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapWithKeyTypeConstructor() { | 	void genericMapWithKeyTypeConstructor() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Map<String, String> input = Map.of( | 		Map<String, String> input = Map.of( | ||||||
| 				"4", "5", | 				"4", "5", | ||||||
| 				"6", "7"); | 				"6", "7"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getLongMap().get(4L)).isEqualTo("5"); | 		assertThat(gb.getLongMap().get(4L)).isEqualTo("5"); | ||||||
| 		assertThat(gb.getLongMap().get(6L)).isEqualTo("7"); | 		assertThat(gb.getLongMap().get(6L)).isEqualTo("7"); | ||||||
| 	} | 	} | ||||||
|  | @ -377,18 +368,18 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapWithCollectionValueConstructor() { | 	void genericMapWithCollectionValueConstructor() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		bf.addPropertyEditorRegistrar(registry -> registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false))); | 		bf.addPropertyEditorRegistrar(registry -> | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); | 				registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false))); | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
| 		Map<String, Collection<?>> input = Map.of( | 		Map<String, Collection<?>> input = Map.of( | ||||||
| 				"1", Set.of(1), | 				"1", Set.of(1), | ||||||
| 				"2", List.of(Boolean.TRUE)); | 				"2", List.of(Boolean.TRUE)); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(Boolean.TRUE); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(Boolean.TRUE); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getCollectionMap().get(1)).isInstanceOf(Set.class); | 		assertThat(gb.getCollectionMap().get(1)).isInstanceOf(Set.class); | ||||||
| 		assertThat(gb.getCollectionMap().get(2)).isInstanceOf(List.class); | 		assertThat(gb.getCollectionMap().get(2)).isInstanceOf(List.class); | ||||||
| 	} | 	} | ||||||
|  | @ -396,32 +387,30 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericSetFactoryMethod() { | 	void genericSetFactoryMethod() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 		rbd.setFactoryMethodName("createInstance"); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
|  | 		bd.setFactoryMethodName("createInstance"); | ||||||
| 		Set<String> input = Set.of("4", "5"); | 		Set<String> input = Set.of("4", "5"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericSetListFactoryMethod() throws Exception { | 	void genericSetListFactoryMethod() throws Exception { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 		rbd.setFactoryMethodName("createInstance"); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
|  | 		bd.setFactoryMethodName("createInstance"); | ||||||
| 		Set<String> input1 = Set.of("4", "5"); | 		Set<String> input1 = Set.of("4", "5"); | ||||||
| 		List<String> input2 = List.of("http://localhost:8080", "http://localhost:9090"); | 		List<String> input2 = List.of("http://localhost:8080", "http://localhost:9090"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input1); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input1); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input2); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input2); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | ||||||
| 		assertThat(gb.getResourceList()) | 		assertThat(gb.getResourceList()) | ||||||
| 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | 				.containsExactly(new UrlResource("http://localhost:8080"), new UrlResource("http://localhost:9090")); | ||||||
|  | @ -430,19 +419,18 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericSetMapFactoryMethod() { | 	void genericSetMapFactoryMethod() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 		rbd.setFactoryMethodName("createInstance"); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
|  | 		bd.setFactoryMethodName("createInstance"); | ||||||
| 		Set<String> input1 = Set.of("4", "5"); | 		Set<String> input1 = Set.of("4", "5"); | ||||||
| 		Map<String, String> input2 = Map.of( | 		Map<String, String> input2 = Map.of( | ||||||
| 				"4", "5", | 				"4", "5", | ||||||
| 				"6", "7"); | 				"6", "7"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input1); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input1); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input2); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input2); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | 		assertThat(gb.getIntegerSet()).containsExactlyInAnyOrder(4, 5); | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | ||||||
|  | @ -451,18 +439,17 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapResourceFactoryMethod() throws Exception { | 	void genericMapResourceFactoryMethod() throws Exception { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 		rbd.setFactoryMethodName("createInstance"); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
|  | 		bd.setFactoryMethodName("createInstance"); | ||||||
| 		Map<String, String> input = Map.of( | 		Map<String, String> input = Map.of( | ||||||
| 				"4", "5", | 				"4", "5", | ||||||
| 				"6", "7"); | 				"6", "7"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue("http://localhost:8080"); | 		bd.getConstructorArgumentValues().addGenericArgumentValue("http://localhost:8080"); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | 		assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); | ||||||
| 		assertThat(gb.getResourceList()).containsExactly(new UrlResource("http://localhost:8080")); | 		assertThat(gb.getResourceList()).containsExactly(new UrlResource("http://localhost:8080")); | ||||||
|  | @ -471,21 +458,20 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapMapFactoryMethod() { | 	void genericMapMapFactoryMethod() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 		rbd.setFactoryMethodName("createInstance"); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
|  | 		bd.setFactoryMethodName("createInstance"); | ||||||
| 		Map<String, String> input1 = Map.of( | 		Map<String, String> input1 = Map.of( | ||||||
| 				"1", "0", | 				"1", "0", | ||||||
| 				"2", "3"); | 				"2", "3"); | ||||||
| 		Map<String, String> input2 = Map.of( | 		Map<String, String> input2 = Map.of( | ||||||
| 				"4", "5", | 				"4", "5", | ||||||
| 				"6", "7"); | 				"6", "7"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input1); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input1); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input2); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input2); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getPlainMap().get("1")).isEqualTo("0"); | 		assertThat(gb.getPlainMap().get("1")).isEqualTo("0"); | ||||||
| 		assertThat(gb.getPlainMap().get("2")).isEqualTo("3"); | 		assertThat(gb.getPlainMap().get("2")).isEqualTo("3"); | ||||||
| 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | 		assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); | ||||||
|  | @ -495,17 +481,16 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapWithKeyTypeFactoryMethod() { | 	void genericMapWithKeyTypeFactoryMethod() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); |  | ||||||
| 		rbd.setFactoryMethodName("createInstance"); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
|  | 		bd.setFactoryMethodName("createInstance"); | ||||||
| 		Map<String, String> input = Map.of( | 		Map<String, String> input = Map.of( | ||||||
| 				"4", "5", | 				"4", "5", | ||||||
| 				"6", "7"); | 				"6", "7"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getLongMap().get(Long.valueOf("4"))).isEqualTo("5"); | 		assertThat(gb.getLongMap().get(Long.valueOf("4"))).isEqualTo("5"); | ||||||
| 		assertThat(gb.getLongMap().get(Long.valueOf("6"))).isEqualTo("7"); | 		assertThat(gb.getLongMap().get(Long.valueOf("6"))).isEqualTo("7"); | ||||||
| 	} | 	} | ||||||
|  | @ -513,19 +498,19 @@ class BeanFactoryGenericsTests { | ||||||
| 	@Test | 	@Test | ||||||
| 	void genericMapWithCollectionValueFactoryMethod() { | 	void genericMapWithCollectionValueFactoryMethod() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		bf.addPropertyEditorRegistrar(registry -> registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false))); | 		bf.addPropertyEditorRegistrar(registry -> | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); | 				registry.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false))); | ||||||
| 		rbd.setFactoryMethodName("createInstance"); |  | ||||||
| 
 | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(GenericBean.class); | ||||||
|  | 		bd.setFactoryMethodName("createInstance"); | ||||||
| 		Map<String, Collection<?>> input = Map.of( | 		Map<String, Collection<?>> input = Map.of( | ||||||
| 				"1", Set.of(1), | 				"1", Set.of(1), | ||||||
| 				"2", List.of(Boolean.TRUE)); | 				"2", List.of(Boolean.TRUE)); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(Boolean.TRUE); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(Boolean.TRUE); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(input); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(input); | ||||||
|  | 		bf.registerBeanDefinition("genericBean", bd); | ||||||
| 
 | 
 | ||||||
| 		bf.registerBeanDefinition("genericBean", rbd); |  | ||||||
| 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | 		GenericBean<?> gb = (GenericBean<?>) bf.getBean("genericBean"); | ||||||
| 
 |  | ||||||
| 		assertThat(gb.getCollectionMap().get(1)).isInstanceOf(Set.class); | 		assertThat(gb.getCollectionMap().get(1)).isInstanceOf(Set.class); | ||||||
| 		assertThat(gb.getCollectionMap().get(2)).isInstanceOf(List.class); | 		assertThat(gb.getCollectionMap().get(2)).isInstanceOf(List.class); | ||||||
| 	} | 	} | ||||||
|  | @ -535,6 +520,7 @@ class BeanFactoryGenericsTests { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | ||||||
| 				new ClassPathResource("genericBeanTests.xml", getClass())); | 				new ClassPathResource("genericBeanTests.xml", getClass())); | ||||||
|  | 
 | ||||||
| 		NamedUrlList list = bf.getBean("list", NamedUrlList.class); | 		NamedUrlList list = bf.getBean("list", NamedUrlList.class); | ||||||
| 		assertThat(list).containsExactly(new URL("http://localhost:8080")); | 		assertThat(list).containsExactly(new URL("http://localhost:8080")); | ||||||
| 	} | 	} | ||||||
|  | @ -544,6 +530,7 @@ class BeanFactoryGenericsTests { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | ||||||
| 				new ClassPathResource("genericBeanTests.xml", getClass())); | 				new ClassPathResource("genericBeanTests.xml", getClass())); | ||||||
|  | 
 | ||||||
| 		NamedUrlSet set = bf.getBean("set", NamedUrlSet.class); | 		NamedUrlSet set = bf.getBean("set", NamedUrlSet.class); | ||||||
| 		assertThat(set).containsExactly(new URL("http://localhost:8080")); | 		assertThat(set).containsExactly(new URL("http://localhost:8080")); | ||||||
| 	} | 	} | ||||||
|  | @ -553,6 +540,7 @@ class BeanFactoryGenericsTests { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | ||||||
| 				new ClassPathResource("genericBeanTests.xml", getClass())); | 				new ClassPathResource("genericBeanTests.xml", getClass())); | ||||||
|  | 
 | ||||||
| 		NamedUrlMap map = bf.getBean("map", NamedUrlMap.class); | 		NamedUrlMap map = bf.getBean("map", NamedUrlMap.class); | ||||||
| 		assertThat(map).containsExactly(entry(10, new URL("http://localhost:8080"))); | 		assertThat(map).containsExactly(entry(10, new URL("http://localhost:8080"))); | ||||||
| 	} | 	} | ||||||
|  | @ -562,6 +550,7 @@ class BeanFactoryGenericsTests { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | ||||||
| 				new ClassPathResource("genericBeanTests.xml", getClass())); | 				new ClassPathResource("genericBeanTests.xml", getClass())); | ||||||
|  | 
 | ||||||
| 		GenericIntegerBean gb = (GenericIntegerBean) bf.getBean("integerBean"); | 		GenericIntegerBean gb = (GenericIntegerBean) bf.getBean("integerBean"); | ||||||
| 		assertThat(gb.getGenericProperty()).isEqualTo(10); | 		assertThat(gb.getGenericProperty()).isEqualTo(10); | ||||||
| 		assertThat(gb.getGenericListProperty()).containsExactly(20, 30); | 		assertThat(gb.getGenericListProperty()).containsExactly(20, 30); | ||||||
|  | @ -572,6 +561,7 @@ class BeanFactoryGenericsTests { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | ||||||
| 				new ClassPathResource("genericBeanTests.xml", getClass())); | 				new ClassPathResource("genericBeanTests.xml", getClass())); | ||||||
|  | 
 | ||||||
| 		GenericSetOfIntegerBean gb = (GenericSetOfIntegerBean) bf.getBean("setOfIntegerBean"); | 		GenericSetOfIntegerBean gb = (GenericSetOfIntegerBean) bf.getBean("setOfIntegerBean"); | ||||||
| 		assertThat(gb.getGenericProperty()).singleElement().isEqualTo(10); | 		assertThat(gb.getGenericProperty()).singleElement().isEqualTo(10); | ||||||
| 		assertThat(gb.getGenericListProperty()).satisfiesExactly( | 		assertThat(gb.getGenericListProperty()).satisfiesExactly( | ||||||
|  | @ -584,6 +574,7 @@ class BeanFactoryGenericsTests { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | 		new XmlBeanDefinitionReader(bf).loadBeanDefinitions( | ||||||
| 				new ClassPathResource("genericBeanTests.xml", getClass())); | 				new ClassPathResource("genericBeanTests.xml", getClass())); | ||||||
|  | 
 | ||||||
| 		UrlSet urlSet = bf.getBean("setBean", UrlSet.class); | 		UrlSet urlSet = bf.getBean("setBean", UrlSet.class); | ||||||
| 		assertThat(urlSet).containsExactly(new URL("https://www.springframework.org")); | 		assertThat(urlSet).containsExactly(new URL("https://www.springframework.org")); | ||||||
| 	} | 	} | ||||||
|  | @ -600,27 +591,27 @@ class BeanFactoryGenericsTests { | ||||||
| 	 */ | 	 */ | ||||||
| 	@Test | 	@Test | ||||||
| 	void parameterizedStaticFactoryMethod() { | 	void parameterizedStaticFactoryMethod() { | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(getClass()); | 		RootBeanDefinition bd = new RootBeanDefinition(getClass()); | ||||||
| 		rbd.setFactoryMethodName("createMockitoMock"); | 		bd.setFactoryMethodName("createMockitoMock"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class); | ||||||
| 
 | 
 | ||||||
| 		assertRunnableMockFactory(rbd); | 		assertRunnableMockFactory(bd); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void parameterizedStaticFactoryMethodWithWrappedClassName() { | 	void parameterizedStaticFactoryMethodWithWrappedClassName() { | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(); | 		RootBeanDefinition bd = new RootBeanDefinition(); | ||||||
| 		rbd.setBeanClassName(getClass().getName()); | 		bd.setBeanClassName(getClass().getName()); | ||||||
| 		rbd.setFactoryMethodName("createMockitoMock"); | 		bd.setFactoryMethodName("createMockitoMock"); | ||||||
| 		// TypedStringValue is used as an equivalent to an XML-defined argument String | 		// TypedStringValue is used as an equivalent to an XML-defined argument String | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(new TypedStringValue(Runnable.class.getName())); | 		bd.getConstructorArgumentValues().addGenericArgumentValue(new TypedStringValue(Runnable.class.getName())); | ||||||
| 
 | 
 | ||||||
| 		assertRunnableMockFactory(rbd); | 		assertRunnableMockFactory(bd); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void assertRunnableMockFactory(RootBeanDefinition rbd) { | 	private void assertRunnableMockFactory(RootBeanDefinition bd) { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		bf.registerBeanDefinition("mock", rbd); | 		bf.registerBeanDefinition("mock", bd); | ||||||
| 
 | 
 | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | ||||||
| 		assertThat(bf.getType("mock")).isEqualTo(Runnable.class); | 		assertThat(bf.getType("mock")).isEqualTo(Runnable.class); | ||||||
|  | @ -643,14 +634,14 @@ class BeanFactoryGenericsTests { | ||||||
| 	void parameterizedInstanceFactoryMethod() { | 	void parameterizedInstanceFactoryMethod() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class); | 		RootBeanDefinition bd1 = new RootBeanDefinition(MocksControl.class); | ||||||
| 		bf.registerBeanDefinition("mocksControl", rbd); | 		bf.registerBeanDefinition("mocksControl", bd1); | ||||||
| 
 | 
 | ||||||
| 		rbd = new RootBeanDefinition(); | 		RootBeanDefinition bd2 = new RootBeanDefinition(); | ||||||
| 		rbd.setFactoryBeanName("mocksControl"); | 		bd2.setFactoryBeanName("mocksControl"); | ||||||
| 		rbd.setFactoryMethodName("createMock"); | 		bd2.setFactoryMethodName("createMock"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class); | 		bd2.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class); | ||||||
| 		bf.registerBeanDefinition("mock", rbd); | 		bf.registerBeanDefinition("mock", bd2); | ||||||
| 
 | 
 | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | ||||||
|  | @ -664,14 +655,14 @@ class BeanFactoryGenericsTests { | ||||||
| 	void parameterizedInstanceFactoryMethodWithNonResolvedClassName() { | 	void parameterizedInstanceFactoryMethodWithNonResolvedClassName() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class); | 		RootBeanDefinition bd1 = new RootBeanDefinition(MocksControl.class); | ||||||
| 		bf.registerBeanDefinition("mocksControl", rbd); | 		bf.registerBeanDefinition("mocksControl", bd1); | ||||||
| 
 | 
 | ||||||
| 		rbd = new RootBeanDefinition(); | 		RootBeanDefinition bd2 = new RootBeanDefinition(); | ||||||
| 		rbd.setFactoryBeanName("mocksControl"); | 		bd2.setFactoryBeanName("mocksControl"); | ||||||
| 		rbd.setFactoryMethodName("createMock"); | 		bd2.setFactoryMethodName("createMock"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class.getName()); | 		bd2.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class.getName()); | ||||||
| 		bf.registerBeanDefinition("mock", rbd); | 		bf.registerBeanDefinition("mock", bd2); | ||||||
| 
 | 
 | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | ||||||
|  | @ -685,14 +676,14 @@ class BeanFactoryGenericsTests { | ||||||
| 	void parameterizedInstanceFactoryMethodWithInvalidClassName() { | 	void parameterizedInstanceFactoryMethodWithInvalidClassName() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class); | 		RootBeanDefinition bd1 = new RootBeanDefinition(MocksControl.class); | ||||||
| 		bf.registerBeanDefinition("mocksControl", rbd); | 		bf.registerBeanDefinition("mocksControl", bd1); | ||||||
| 
 | 
 | ||||||
| 		rbd = new RootBeanDefinition(); | 		RootBeanDefinition rbd2 = new RootBeanDefinition(); | ||||||
| 		rbd.setFactoryBeanName("mocksControl"); | 		rbd2.setFactoryBeanName("mocksControl"); | ||||||
| 		rbd.setFactoryMethodName("createMock"); | 		rbd2.setFactoryMethodName("createMock"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue("x"); | 		rbd2.getConstructorArgumentValues().addGenericArgumentValue("x"); | ||||||
| 		bf.registerBeanDefinition("mock", rbd); | 		bf.registerBeanDefinition("mock", rbd2); | ||||||
| 
 | 
 | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isFalse(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isFalse(); | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isFalse(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isFalse(); | ||||||
|  | @ -706,14 +697,14 @@ class BeanFactoryGenericsTests { | ||||||
| 	void parameterizedInstanceFactoryMethodWithIndexedArgument() { | 	void parameterizedInstanceFactoryMethodWithIndexedArgument() { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class); | 		RootBeanDefinition bd1 = new RootBeanDefinition(MocksControl.class); | ||||||
| 		bf.registerBeanDefinition("mocksControl", rbd); | 		bf.registerBeanDefinition("mocksControl", bd1); | ||||||
| 
 | 
 | ||||||
| 		rbd = new RootBeanDefinition(); | 		RootBeanDefinition bd2 = new RootBeanDefinition(); | ||||||
| 		rbd.setFactoryBeanName("mocksControl"); | 		bd2.setFactoryBeanName("mocksControl"); | ||||||
| 		rbd.setFactoryMethodName("createMock"); | 		bd2.setFactoryMethodName("createMock"); | ||||||
| 		rbd.getConstructorArgumentValues().addIndexedArgumentValue(0, Runnable.class); | 		bd2.getConstructorArgumentValues().addIndexedArgumentValue(0, Runnable.class); | ||||||
| 		bf.registerBeanDefinition("mock", rbd); | 		bf.registerBeanDefinition("mock", bd2); | ||||||
| 
 | 
 | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | ||||||
|  | @ -728,14 +719,14 @@ class BeanFactoryGenericsTests { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		bf.setTempClassLoader(new OverridingClassLoader(getClass().getClassLoader())); | 		bf.setTempClassLoader(new OverridingClassLoader(getClass().getClassLoader())); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class); | 		RootBeanDefinition bd1 = new RootBeanDefinition(MocksControl.class); | ||||||
| 		bf.registerBeanDefinition("mocksControl", rbd); | 		bf.registerBeanDefinition("mocksControl", bd1); | ||||||
| 
 | 
 | ||||||
| 		rbd = new RootBeanDefinition(); | 		RootBeanDefinition bd2 = new RootBeanDefinition(); | ||||||
| 		rbd.setFactoryBeanName("mocksControl"); | 		bd2.setFactoryBeanName("mocksControl"); | ||||||
| 		rbd.setFactoryMethodName("createMock"); | 		bd2.setFactoryMethodName("createMock"); | ||||||
| 		rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class); | 		bd2.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class); | ||||||
| 		bf.registerBeanDefinition("mock", rbd); | 		bf.registerBeanDefinition("mock", bd2); | ||||||
| 
 | 
 | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | ||||||
| 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | 		assertThat(bf.isTypeMatch("mock", Runnable.class)).isTrue(); | ||||||
|  | @ -767,25 +758,31 @@ class BeanFactoryGenericsTests { | ||||||
| 		assertThat(floatStoreNames).isEmpty(); | 		assertThat(floatStoreNames).isEmpty(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@ParameterizedTest | ||||||
| 	void genericMatchingWithFullTypeDifferentiation() { | 	@ValueSource(classes = {NumberStoreFactory.class, NumberStoreFactoryBeans.class}) | ||||||
|  | 	void genericMatchingWithFullTypeDifferentiation(Class<?> factoryClass) { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); | 		bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); | ||||||
| 		bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); | 		bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition bd1 = new RootBeanDefinition(NumberStoreFactory.class); | 		RootBeanDefinition bd1 = new RootBeanDefinition(factoryClass); | ||||||
| 		bd1.setFactoryMethodName("newDoubleStore"); | 		bd1.setFactoryMethodName("newDoubleStore"); | ||||||
| 		bf.registerBeanDefinition("store1", bd1); | 		bf.registerBeanDefinition("store1", bd1); | ||||||
| 		RootBeanDefinition bd2 = new RootBeanDefinition(NumberStoreFactory.class); | 		RootBeanDefinition bd2 = new RootBeanDefinition(factoryClass); | ||||||
| 		bd2.setFactoryMethodName("newFloatStore"); | 		bd2.setFactoryMethodName("newFloatStore"); | ||||||
| 		bf.registerBeanDefinition("store2", bd2); | 		bf.registerBeanDefinition("store2", bd2); | ||||||
| 		bf.registerBeanDefinition("numberBean", | 		RootBeanDefinition bd3 = new RootBeanDefinition(NumberBean.class); | ||||||
| 				new RootBeanDefinition(NumberBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR, false)); | 		bd3.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); | ||||||
|  | 		bd3.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); | ||||||
|  | 		bf.registerBeanDefinition("numberBean", bd3); | ||||||
| 
 | 
 | ||||||
| 		NumberBean nb = bf.getBean(NumberBean.class); |  | ||||||
| 		NumberStore<?> store1 = bf.getBean("store1", NumberStore.class); | 		NumberStore<?> store1 = bf.getBean("store1", NumberStore.class); | ||||||
| 		assertThat(nb.getDoubleStore()).isSameAs(store1); |  | ||||||
| 		NumberStore<?> store2 = bf.getBean("store2", NumberStore.class); | 		NumberStore<?> store2 = bf.getBean("store2", NumberStore.class); | ||||||
|  | 		NumberBean nb = bf.getBean(NumberBean.class); | ||||||
|  | 		assertThat(nb.getDoubleStore()).isSameAs(store1); | ||||||
|  | 		assertThat(nb.getFloatStore()).isSameAs(store2); | ||||||
|  | 		nb = bf.getBean(NumberBean.class); | ||||||
|  | 		assertThat(nb.getDoubleStore()).isSameAs(store1); | ||||||
| 		assertThat(nb.getFloatStore()).isSameAs(store2); | 		assertThat(nb.getFloatStore()).isSameAs(store2); | ||||||
| 
 | 
 | ||||||
| 		String[] numberStoreNames = bf.getBeanNamesForType(ResolvableType.forClass(NumberStore.class)); | 		String[] numberStoreNames = bf.getBeanNamesForType(ResolvableType.forClass(NumberStore.class)); | ||||||
|  | @ -833,16 +830,17 @@ class BeanFactoryGenericsTests { | ||||||
| 		assertThat(floatStoreProvider.orderedStream()).singleElement().isEqualTo(store2); | 		assertThat(floatStoreProvider.orderedStream()).singleElement().isEqualTo(store2); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@ParameterizedTest | ||||||
| 	void genericMatchingWithUnresolvedOrderedStream() { | 	@ValueSource(classes = {NumberStoreFactory.class, NumberStoreFactoryBeans.class}) | ||||||
|  | 	void genericMatchingWithUnresolvedOrderedStream(Class<?> factoryClass) { | ||||||
| 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
| 		bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); | 		bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); | ||||||
| 		bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); | 		bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition bd1 = new RootBeanDefinition(NumberStoreFactory.class); | 		RootBeanDefinition bd1 = new RootBeanDefinition(factoryClass); | ||||||
| 		bd1.setFactoryMethodName("newDoubleStore"); | 		bd1.setFactoryMethodName("newDoubleStore"); | ||||||
| 		bf.registerBeanDefinition("store1", bd1); | 		bf.registerBeanDefinition("store1", bd1); | ||||||
| 		RootBeanDefinition bd2 = new RootBeanDefinition(NumberStoreFactory.class); | 		RootBeanDefinition bd2 = new RootBeanDefinition(factoryClass); | ||||||
| 		bd2.setFactoryMethodName("newFloatStore"); | 		bd2.setFactoryMethodName("newFloatStore"); | ||||||
| 		bf.registerBeanDefinition("store2", bd2); | 		bf.registerBeanDefinition("store2", bd2); | ||||||
| 
 | 
 | ||||||
|  | @ -857,15 +855,35 @@ class BeanFactoryGenericsTests { | ||||||
| 		bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); | 		bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); | ||||||
| 
 | 
 | ||||||
| 		RootBeanDefinition bd = new RootBeanDefinition(MyFactoryBean.class); | 		RootBeanDefinition bd = new RootBeanDefinition(MyFactoryBean.class); | ||||||
| 		// Replicate org.springframework.data.repository.config.RepositoryConfigurationDelegate#registerRepositoriesIn |  | ||||||
| 		// behavior of setting targetType, required to hit other branch in |  | ||||||
| 		// org.springframework.beans.factory.support.GenericTypeAwareAutowireCandidateResolver.checkGenericTypeMatch |  | ||||||
| 		bd.setTargetType(ResolvableType.forClassWithGenerics(MyFactoryBean.class, String.class)); | 		bd.setTargetType(ResolvableType.forClassWithGenerics(MyFactoryBean.class, String.class)); | ||||||
| 		bf.registerBeanDefinition("myFactoryBean", bd); | 		bf.registerBeanDefinition("myFactoryBean", bd); | ||||||
| 		bf.registerBeanDefinition("myFactoryBeanHolder", | 		bf.registerBeanDefinition("myFactoryBeanHolder", | ||||||
| 				new RootBeanDefinition(MyFactoryBeanHolder.class, AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR, false)); | 				new RootBeanDefinition(MyFactoryBeanHolder.class, AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR, false)); | ||||||
| 
 | 
 | ||||||
| 		assertThat(bf.getBean(MyFactoryBeanHolder.class).factoryBeans).contains(bf.getBean(MyFactoryBean.class)); | 		assertThat(bf.getBean(MyFactoryBeanHolder.class).factoryBeans).containsOnly(bf.getBean(MyFactoryBean.class)); | ||||||
|  | 		assertThat(bf.getBeanProvider(MyGenericInterfaceForFactoryBeans.class)).containsOnly(bf.getBean(MyFactoryBean.class)); | ||||||
|  | 		assertThat(bf.getBeanProvider(bd.getResolvableType())).containsOnly(bf.getBean(MyFactoryBean.class)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test  // gh-32489 | ||||||
|  | 	void genericMatchingAgainstLazyFactoryBeanClass() { | ||||||
|  | 		DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); | ||||||
|  | 		bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); | ||||||
|  | 
 | ||||||
|  | 		RootBeanDefinition bd = new RootBeanDefinition(MyFactoryBean.class); | ||||||
|  | 		// Replicate org.springframework.data.repository.config.RepositoryConfigurationDelegate#registerRepositoriesIn | ||||||
|  | 		// behavior of setting targetType, required to hit other branch in | ||||||
|  | 		// org.springframework.beans.factory.support.GenericTypeAwareAutowireCandidateResolver.checkGenericTypeMatch | ||||||
|  | 		bd.setTargetType(ResolvableType.forClassWithGenerics(MyFactoryBean.class, String.class)); | ||||||
|  | 		bd.setLazyInit(true); | ||||||
|  | 		bf.registerBeanDefinition("myFactoryBean", bd); | ||||||
|  | 		bf.registerBeanDefinition("myFactoryBeanHolder", | ||||||
|  | 				new RootBeanDefinition(MyFactoryBeanHolder.class, AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR, false)); | ||||||
|  | 
 | ||||||
|  | 		assertThat(bf.getBeanProvider(bd.getResolvableType())).containsOnly(bf.getBean(MyFactoryBean.class)); | ||||||
|  | 		assertThat(bf.getBeanProvider(MyGenericInterfaceForFactoryBeans.class)).containsOnly(bf.getBean(MyFactoryBean.class)); | ||||||
|  | 		assertThat(bf.getBean(MyFactoryBeanHolder.class).factoryBeans).containsOnly(bf.getBean(MyFactoryBean.class)); | ||||||
|  | 		assertThat(bf.getBeanProvider(bd.getResolvableType())).containsOnly(bf.getBean(MyFactoryBean.class)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -985,6 +1003,38 @@ class BeanFactoryGenericsTests { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 	public static class NumberStoreFactoryBeans { | ||||||
|  | 
 | ||||||
|  | 		@Order(1) | ||||||
|  | 		public static FactoryBean<NumberStore<Double>> newDoubleStore() { | ||||||
|  | 			return new FactoryBean<>() { | ||||||
|  | 				@Override | ||||||
|  | 				public NumberStore<Double> getObject() { | ||||||
|  | 					return new DoubleStore(); | ||||||
|  | 				} | ||||||
|  | 				@Override | ||||||
|  | 				public Class<?> getObjectType() { | ||||||
|  | 					return DoubleStore.class; | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		@Order(0) | ||||||
|  | 		public static FactoryBean<NumberStore<Float>> newFloatStore() { | ||||||
|  | 			return new FactoryBean<>() { | ||||||
|  | 				@Override | ||||||
|  | 				public NumberStore<Float> getObject() { | ||||||
|  | 					return new FloatStore(); | ||||||
|  | 				} | ||||||
|  | 				@Override | ||||||
|  | 				public Class<?> getObjectType() { | ||||||
|  | 					return FloatStore.class; | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 	public interface MyGenericInterfaceForFactoryBeans<T> { | 	public interface MyGenericInterfaceForFactoryBeans<T> { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -409,15 +409,17 @@ class AnnotationConfigApplicationContextTests { | ||||||
| 		bd2.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, Integer.class))); | 		bd2.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, Integer.class))); | ||||||
| 		bd2.setLazyInit(true); | 		bd2.setLazyInit(true); | ||||||
| 		context.registerBeanDefinition("fb2", bd2); | 		context.registerBeanDefinition("fb2", bd2); | ||||||
| 		context.registerBeanDefinition("ip", new RootBeanDefinition(FactoryBeanInjectionPoints.class)); | 		RootBeanDefinition bd3 = new RootBeanDefinition(FactoryBeanInjectionPoints.class); | ||||||
|  | 		bd3.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); | ||||||
|  | 		context.registerBeanDefinition("ip", bd3); | ||||||
| 		context.refresh(); | 		context.refresh(); | ||||||
| 
 | 
 | ||||||
|  | 		assertThat(context.getBean("ip", FactoryBeanInjectionPoints.class).factoryBean).isSameAs(context.getBean("&fb1")); | ||||||
|  | 		assertThat(context.getBean("ip", FactoryBeanInjectionPoints.class).factoryResult).isSameAs(context.getBean("fb1")); | ||||||
| 		assertThat(context.getType("&fb1")).isEqualTo(GenericHolderFactoryBean.class); | 		assertThat(context.getType("&fb1")).isEqualTo(GenericHolderFactoryBean.class); | ||||||
| 		assertThat(context.getType("fb1")).isEqualTo(GenericHolder.class); | 		assertThat(context.getType("fb1")).isEqualTo(GenericHolder.class); | ||||||
| 		assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2); | 		assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2); | ||||||
| 		assertThat(context.getBeanNamesForType(GenericHolderFactoryBean.class)).hasSize(1); | 		assertThat(context.getBeanNamesForType(GenericHolderFactoryBean.class)).hasSize(1); | ||||||
| 		assertThat(context.getBean("ip", FactoryBeanInjectionPoints.class).factoryBean).isSameAs(context.getBean("&fb1")); |  | ||||||
| 		assertThat(context.getBean("ip", FactoryBeanInjectionPoints.class).factoryResult).isSameAs(context.getBean("fb1")); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
|  | @ -425,7 +427,7 @@ class AnnotationConfigApplicationContextTests { | ||||||
| 		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); | 		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); | ||||||
| 		RootBeanDefinition bd1 = new RootBeanDefinition(); | 		RootBeanDefinition bd1 = new RootBeanDefinition(); | ||||||
| 		bd1.setBeanClass(GenericHolderFactoryBean.class); | 		bd1.setBeanClass(GenericHolderFactoryBean.class); | ||||||
| 		bd1.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, Object.class))); | 		bd1.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, String.class))); | ||||||
| 		bd1.setLazyInit(true); | 		bd1.setLazyInit(true); | ||||||
| 		context.registerBeanDefinition("fb1", bd1); | 		context.registerBeanDefinition("fb1", bd1); | ||||||
| 		RootBeanDefinition bd2 = new RootBeanDefinition(); | 		RootBeanDefinition bd2 = new RootBeanDefinition(); | ||||||
|  | @ -433,13 +435,19 @@ class AnnotationConfigApplicationContextTests { | ||||||
| 		bd2.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, Integer.class))); | 		bd2.setTargetType(ResolvableType.forClassWithGenerics(FactoryBean.class, ResolvableType.forClassWithGenerics(GenericHolder.class, Integer.class))); | ||||||
| 		bd2.setLazyInit(true); | 		bd2.setLazyInit(true); | ||||||
| 		context.registerBeanDefinition("fb2", bd2); | 		context.registerBeanDefinition("fb2", bd2); | ||||||
| 		context.registerBeanDefinition("ip", new RootBeanDefinition(FactoryResultInjectionPoint.class)); | 		RootBeanDefinition bd3 = new RootBeanDefinition(FactoryBeanInjectionPoints.class); | ||||||
|  | 		bd3.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); | ||||||
|  | 		context.registerBeanDefinition("ip", bd3); | ||||||
| 		context.refresh(); | 		context.refresh(); | ||||||
| 
 | 
 | ||||||
|  | 		assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1")); | ||||||
|  | 		assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1")); | ||||||
| 		assertThat(context.getType("&fb1")).isEqualTo(GenericHolderFactoryBean.class); | 		assertThat(context.getType("&fb1")).isEqualTo(GenericHolderFactoryBean.class); | ||||||
| 		assertThat(context.getType("fb1")).isEqualTo(GenericHolder.class); | 		assertThat(context.getType("fb1")).isEqualTo(GenericHolder.class); | ||||||
| 		assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2); | 		assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2); | ||||||
| 		assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1")); | 		assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2); | ||||||
|  | 		assertThat(context.getBeanProvider(ResolvableType.forClassWithGenerics(GenericHolder.class, String.class))) | ||||||
|  | 				.containsOnly(context.getBean("fb1")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
|  | @ -453,14 +461,19 @@ class AnnotationConfigApplicationContextTests { | ||||||
| 		bd2.setBeanClass(UntypedFactoryBean.class); | 		bd2.setBeanClass(UntypedFactoryBean.class); | ||||||
| 		bd2.setTargetType(ResolvableType.forClassWithGenerics(GenericHolder.class, Integer.class)); | 		bd2.setTargetType(ResolvableType.forClassWithGenerics(GenericHolder.class, Integer.class)); | ||||||
| 		context.registerBeanDefinition("fb2", bd2); | 		context.registerBeanDefinition("fb2", bd2); | ||||||
| 		context.registerBeanDefinition("ip", new RootBeanDefinition(FactoryResultInjectionPoint.class)); | 		RootBeanDefinition bd3 = new RootBeanDefinition(FactoryResultInjectionPoint.class); | ||||||
|  | 		bd3.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); | ||||||
|  | 		context.registerBeanDefinition("ip", bd3); | ||||||
| 		context.refresh(); | 		context.refresh(); | ||||||
| 
 | 
 | ||||||
|  | 		assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1")); | ||||||
|  | 		assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1")); | ||||||
| 		assertThat(context.getType("&fb1")).isEqualTo(GenericHolderFactoryBean.class); | 		assertThat(context.getType("&fb1")).isEqualTo(GenericHolderFactoryBean.class); | ||||||
| 		assertThat(context.getType("fb1")).isEqualTo(GenericHolder.class); | 		assertThat(context.getType("fb1")).isEqualTo(GenericHolder.class); | ||||||
| 		assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2); | 		assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(2); | ||||||
| 		assertThat(context.getBeanNamesForType(GenericHolderFactoryBean.class)).hasSize(1); | 		assertThat(context.getBeanNamesForType(GenericHolderFactoryBean.class)).hasSize(1); | ||||||
| 		assertThat(context.getBean("ip", FactoryResultInjectionPoint.class).factoryResult).isSameAs(context.getBean("fb1")); | 		assertThat(context.getBeanProvider(ResolvableType.forClassWithGenerics(GenericHolder.class, String.class))) | ||||||
|  | 				.containsOnly(context.getBean("fb1")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
|  | @ -480,6 +493,9 @@ class AnnotationConfigApplicationContextTests { | ||||||
| 		assertThat(context.getType("fb")).isEqualTo(String.class); | 		assertThat(context.getType("fb")).isEqualTo(String.class); | ||||||
| 		assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(1); | 		assertThat(context.getBeanNamesForType(FactoryBean.class)).hasSize(1); | ||||||
| 		assertThat(context.getBeanNamesForType(TypedFactoryBean.class)).hasSize(1); | 		assertThat(context.getBeanNamesForType(TypedFactoryBean.class)).hasSize(1); | ||||||
|  | 		assertThat(context.getBeanProvider(String.class)).containsOnly(context.getBean("fb", String.class)); | ||||||
|  | 		assertThat(context.getBeanProvider(ResolvableType.forClassWithGenerics(FactoryBean.class, String.class))) | ||||||
|  | 				.containsOnly(context.getBean("&fb")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
|  |  | ||||||
|  | @ -18,7 +18,6 @@ package org.springframework.context.annotation; | ||||||
| 
 | 
 | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import org.junit.jupiter.api.Disabled; |  | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| 
 | 
 | ||||||
| import org.springframework.beans.BeanUtils; | import org.springframework.beans.BeanUtils; | ||||||
|  | @ -67,8 +66,7 @@ public class Gh32489Tests { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	@Disabled | 	void provideFactoryBeanWithMatchingGenerics() { | ||||||
| 	void resolveFactoryBeanWithMatchingGeneric() { |  | ||||||
| 		try (AnnotationConfigApplicationContext context = prepareContext()) { | 		try (AnnotationConfigApplicationContext context = prepareContext()) { | ||||||
| 			context.refresh(); | 			context.refresh(); | ||||||
| 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(SimpleRepositoryFactoryBean.class, | 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(SimpleRepositoryFactoryBean.class, | ||||||
|  | @ -78,7 +76,7 @@ public class Gh32489Tests { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void resolveFactoryBeanWithFirstNonMatchingGeneric() { | 	void provideFactoryBeanWithFirstNonMatchingGenerics() { | ||||||
| 		try (AnnotationConfigApplicationContext context = prepareContext()) { | 		try (AnnotationConfigApplicationContext context = prepareContext()) { | ||||||
| 			context.refresh(); | 			context.refresh(); | ||||||
| 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(SimpleRepositoryFactoryBean.class, | 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(SimpleRepositoryFactoryBean.class, | ||||||
|  | @ -88,7 +86,7 @@ public class Gh32489Tests { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void resolveFactoryBeanWithSecondNonMatchingGeneric() { | 	void provideFactoryBeanWithSecondNonMatchingGenerics() { | ||||||
| 		try (AnnotationConfigApplicationContext context = prepareContext()) { | 		try (AnnotationConfigApplicationContext context = prepareContext()) { | ||||||
| 			context.refresh(); | 			context.refresh(); | ||||||
| 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(SimpleRepositoryFactoryBean.class, | 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(SimpleRepositoryFactoryBean.class, | ||||||
|  | @ -98,7 +96,7 @@ public class Gh32489Tests { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void resolveFactoryBeanTargetTypeWithMatchingGeneric() { | 	void provideFactoryBeanTargetTypeWithMatchingGenerics() { | ||||||
| 		try (AnnotationConfigApplicationContext context = prepareContext()) { | 		try (AnnotationConfigApplicationContext context = prepareContext()) { | ||||||
| 			context.refresh(); | 			context.refresh(); | ||||||
| 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(Repository.class, | 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(Repository.class, | ||||||
|  | @ -109,7 +107,7 @@ public class Gh32489Tests { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void resolveFactoryBeanTargetTypeWithFirstNonMatchingGeneric() { | 	void provideFactoryBeanTargetTypeWithFirstNonMatchingGenerics() { | ||||||
| 		try (AnnotationConfigApplicationContext context = prepareContext()) { | 		try (AnnotationConfigApplicationContext context = prepareContext()) { | ||||||
| 			context.refresh(); | 			context.refresh(); | ||||||
| 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(Repository.class, | 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(Repository.class, | ||||||
|  | @ -119,7 +117,7 @@ public class Gh32489Tests { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void resolveFactoryBeanTargetTypeWithSecondNonMatchingGeneric() { | 	void provideFactoryBeanTargetTypeWithSecondNonMatchingGenerics() { | ||||||
| 		try (AnnotationConfigApplicationContext context = prepareContext()) { | 		try (AnnotationConfigApplicationContext context = prepareContext()) { | ||||||
| 			context.refresh(); | 			context.refresh(); | ||||||
| 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(Repository.class, | 			ResolvableType requiredType = ResolvableType.forClassWithGenerics(Repository.class, | ||||||
|  | @ -143,21 +141,18 @@ public class Gh32489Tests { | ||||||
| 
 | 
 | ||||||
| 		@Autowired | 		@Autowired | ||||||
| 		List<SimpleRepositoryFactoryBean<?, ?>> repositoryFactoryies; | 		List<SimpleRepositoryFactoryBean<?, ?>> repositoryFactoryies; | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	static class RepositoryFactoriesInformationHolder { | 	static class RepositoryFactoriesInformationHolder { | ||||||
| 
 | 
 | ||||||
| 		@Autowired | 		@Autowired | ||||||
| 		List<RepositoryFactoryInformation<?, ?>> repositoryFactoresInformation; | 		List<RepositoryFactoryInformation<?, ?>> repositoryFactoresInformation; | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	static class RepositoryFactoryHolder { | 	static class RepositoryFactoryHolder { | ||||||
| 
 | 
 | ||||||
| 		@Autowired | 		@Autowired | ||||||
| 		SimpleRepositoryFactoryBean<EmployeeRepository, Long> repositoryFactory; | 		SimpleRepositoryFactoryBean<EmployeeRepository, Long> repositoryFactory; | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	static class SimpleRepositoryFactoryBean<T, ID> extends RepositoryFactoryBeanSupport<T, ID> { | 	static class SimpleRepositoryFactoryBean<T, ID> extends RepositoryFactoryBeanSupport<T, ID> { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue