diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java index 698a04d2498..77f5301c486 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -35,6 +35,7 @@ import org.springframework.cglib.proxy.Factory; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import org.springframework.cglib.proxy.NoOp; +import org.springframework.core.ResolvableType; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -244,8 +245,10 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt return (bean.equals(null) ? null : bean); } else { - return (argsToUse != null ? this.owner.getBean(method.getReturnType(), argsToUse) : - this.owner.getBean(method.getReturnType())); + // Find target bean matching the (potentially generic) method return type + ResolvableType genericReturnType = ResolvableType.forMethodReturnType(method); + return (argsToUse != null ? this.owner.getBeanProvider(genericReturnType).getObject(argsToUse) : + this.owner.getBeanProvider(genericReturnType).getObject()); } } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/LookupOverride.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/LookupOverride.java index b424c38bb08..c441bf7e9cc 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/LookupOverride.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/LookupOverride.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2021 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. @@ -19,17 +19,25 @@ package org.springframework.beans.factory.support; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import org.springframework.core.ResolvableType; import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; /** - * Represents an override of a method that looks up an object in the same IoC context. + * Represents an override of a method that looks up an object in the same IoC context, + * either by bean name or by bean type (based on the declared method return type). * - *
Methods eligible for lookup override must not have arguments. + *
Methods eligible for lookup override may declare arguments in which case the + * given arguments are passed to the bean retrieval operation. * * @author Rod Johnson * @author Juergen Hoeller * @since 1.1 + * @see org.springframework.beans.factory.BeanFactory#getBean(String) + * @see org.springframework.beans.factory.BeanFactory#getBean(Class) + * @see org.springframework.beans.factory.BeanFactory#getBean(String, Object...) + * @see org.springframework.beans.factory.BeanFactory#getBean(Class, Object...) + * @see org.springframework.beans.factory.BeanFactory#getBeanProvider(ResolvableType) */ public class LookupOverride extends MethodOverride { @@ -43,8 +51,8 @@ public class LookupOverride extends MethodOverride { /** * Construct a new LookupOverride. * @param methodName the name of the method to override - * @param beanName the name of the bean in the current {@code BeanFactory} - * that the overridden method should return (may be {@code null}) + * @param beanName the name of the bean in the current {@code BeanFactory} that the + * overridden method should return (may be {@code null} for type-based bean retrieval) */ public LookupOverride(String methodName, @Nullable String beanName) { super(methodName); @@ -53,9 +61,9 @@ public class LookupOverride extends MethodOverride { /** * Construct a new LookupOverride. - * @param method the method to override - * @param beanName the name of the bean in the current {@code BeanFactory} - * that the overridden method should return (may be {@code null}) + * @param method the method declaration to override + * @param beanName the name of the bean in the current {@code BeanFactory} that the + * overridden method should return (may be {@code null} for type-based bean retrieval) */ public LookupOverride(Method method, @Nullable String beanName) { super(method.getName()); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodReplacer.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodReplacer.java index 5677d944ff3..e4e5df879e5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodReplacer.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodReplacer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2021 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. @@ -19,9 +19,8 @@ package org.springframework.beans.factory.support; import java.lang.reflect.Method; /** - * Interface to be implemented by classes that can reimplement any method - * on an IoC-managed object: the Method Injection form of - * Dependency Injection. + * Interface to be implemented by classes that can reimplement any method on an + * IoC-managed object: the Method Injection form of Dependency Injection. * *
Such methods may be (but need not be) abstract, in which case the * container will create a concrete subclass to instantiate. diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java index 1b51bf70655..80f866d21cc 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -25,7 +25,7 @@ import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** - * Extension of MethodOverride that represents an arbitrary + * Extension of {@link MethodOverride} that represents an arbitrary * override of a method by the IoC container. * *
Any non-final method can be overridden, irrespective of its
@@ -45,7 +45,7 @@ public class ReplaceOverride extends MethodOverride {
/**
* Construct a new ReplaceOverride.
* @param methodName the name of the method to override
- * @param methodReplacerBeanName the bean name of the MethodReplacer
+ * @param methodReplacerBeanName the bean name of the {@link MethodReplacer}
*/
public ReplaceOverride(String methodName, String methodReplacerBeanName) {
super(methodName);
diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java
index bd30b5b44c2..afa61bd9a60 100644
--- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java
+++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -121,6 +121,18 @@ public class LookupAnnotationTests {
assertThat(beanFactory.getBean(BeanConsumer.class).abstractBean).isSameAs(bean);
}
+ @Test
+ public void testWithGenericBean() {
+ beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class));
+ beanFactory.registerBeanDefinition("doubleStore", new RootBeanDefinition(DoubleStore.class));
+ beanFactory.registerBeanDefinition("floatStore", new RootBeanDefinition(FloatStore.class));
+
+ NumberBean bean = (NumberBean) beanFactory.getBean("numberBean");
+ assertThat(bean).isNotNull();
+ assertThat(beanFactory.getBean(DoubleStore.class)).isSameAs(bean.getDoubleStore());
+ assertThat(beanFactory.getBean(FloatStore.class)).isSameAs(bean.getFloatStore());
+ }
+
public static abstract class AbstractBean {
@@ -147,4 +159,26 @@ public class LookupAnnotationTests {
AbstractBean abstractBean;
}
+
+ public static class NumberStore