Skip to content

Commit d7309b0

Browse files
committed
Fix: type matching for request-scope generic beans
Signed-off-by: currenjin <[email protected]>
1 parent ac0136b commit d7309b0

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.concurrent.ConcurrentHashMap;
3030
import java.util.concurrent.CopyOnWriteArrayList;
3131
import java.util.function.Predicate;
32+
import java.util.function.Supplier;
3233
import java.util.function.UnaryOperator;
3334

3435
import org.springframework.beans.BeanUtils;
@@ -583,6 +584,27 @@ else if (typeToMatch.hasGenerics() && containsBeanDefinition(beanName)) {
583584
// Generics potentially only match on the target class, not on the proxy...
584585
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
585586
Class<?> targetType = mbd.getTargetType();
587+
588+
String scope = mbd.getScope();
589+
if (targetType == null && scope != null && !scope.isEmpty()) {
590+
String targetBeanName = "scopedTarget." + beanName;
591+
if (containsBeanDefinition(targetBeanName)) {
592+
RootBeanDefinition targetMbd = getMergedLocalBeanDefinition(targetBeanName);
593+
594+
ResolvableType targetResolvableType = targetMbd.targetType;
595+
if (targetResolvableType == null) {
596+
targetResolvableType = targetMbd.factoryMethodReturnType;
597+
}
598+
if (targetResolvableType == null) {
599+
targetResolvableType = ResolvableType.forClass(targetMbd.getBeanClass());
600+
}
601+
602+
if (typeToMatch.isAssignableFrom(targetResolvableType)) {
603+
return true;
604+
}
605+
}
606+
}
607+
586608
if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) {
587609
// Check raw class match as well, making sure it's exposed on the proxy.
588610
Class<?> classToMatch = typeToMatch.resolve();
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.springframework.beans.factory.support;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.springframework.core.ResolvableType;
5+
6+
import java.util.function.Supplier;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
/**
11+
* Tests for {@link AbstractBeanFactory#isTypeMatch} with scoped proxy beans that use generic types.
12+
*/
13+
class ScopedProxyGenericTypeMatchTests {
14+
15+
@Test
16+
void scopedProxyBeanTypeMatching() {
17+
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
18+
19+
RootBeanDefinition targetDef = new RootBeanDefinition(SomeGenericSupplier.class);
20+
targetDef.setScope("request");
21+
factory.registerBeanDefinition("scopedTarget.wordBean", targetDef);
22+
23+
RootBeanDefinition proxyDef = new RootBeanDefinition();
24+
proxyDef.setScope("singleton");
25+
proxyDef.setTargetType(ResolvableType.forClassWithGenerics(Supplier.class, String.class));
26+
proxyDef.setAttribute("targetBeanName", "scopedTarget.wordBean");
27+
factory.registerBeanDefinition("wordBean", proxyDef);
28+
29+
ResolvableType supplierType = ResolvableType.forClassWithGenerics(Supplier.class, String.class);
30+
31+
boolean isMatch = factory.isTypeMatch("wordBean", supplierType);
32+
33+
34+
assertThat(isMatch).isTrue();
35+
36+
String[] names = factory.getBeanNamesForType(supplierType);
37+
assertThat(names).contains("wordBean");
38+
}
39+
40+
static class SomeGenericSupplier implements Supplier<String> {
41+
@Override
42+
public String get() {
43+
return "value";
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)