Fix BeanFactory.getBean(String, ParameterizedTypeReference) to respect AOP proxy

Before this commit, the implementation uses `ResolvableType::isInstance` which doesn't take JDK proxy into account, it fails if `proxyTargetClass = false`:

```
Bean named 'userDao' is expected to be of type 'org.springframework.cache.config.ExpressionCachingIntegrationTests$BaseDao<org.springframework.cache.config.ExpressionCachingIntegrationTests$User>' but was actually of type 'org.springframework.cache.config.$Proxy53'
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'userDao' is expected to be of type 'org.springframework.cache.config.ExpressionCachingIntegrationTests$BaseDao<org.springframework.cache.config.ExpressionCachingIntegrationTests$User>' but was actually of type 'org.springframework.cache.config.$Proxy53'
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:212)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1312)
	at org.springframework.cache.config.ExpressionCachingIntegrationTests.expressionIsCacheBasedOnActualMethod(ExpressionCachingIntegrationTests.java:42)
```

See gh-34687
Closes gh-37047

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
This commit is contained in:
Yanming Zhou
2026-09-14 15:57:07 +02:00
committed by GitHub
parent 05a1075b69
commit 74a6c1c328
2 changed files with 5 additions and 4 deletions
@@ -208,7 +208,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
public <T> T getBean(String name, ParameterizedTypeReference<T> typeReference) throws BeansException {
Object bean = getBean(name);
Type requiredType = typeReference.getType();
if (!ResolvableType.forType(requiredType).isInstance(bean)) {
if (!isTypeMatch(name, ResolvableType.forType(requiredType), true)) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) bean;
@@ -27,20 +27,21 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.ParameterizedTypeReference;
/**
* @author Stephane Nicoll
* @author Yanming Zhou
*/
class ExpressionCachingIntegrationTests {
@Test // SPR-11692
@SuppressWarnings("unchecked")
void expressionIsCacheBasedOnActualMethod() {
ConfigurableApplicationContext context =
new AnnotationConfigApplicationContext(SharedConfig.class, Spr11692Config.class);
BaseDao<User> userDao = (BaseDao<User>) context.getBean("userDao");
BaseDao<Order> orderDao = (BaseDao<Order>) context.getBean("orderDao");
BaseDao<User> userDao = context.getBean("userDao", new ParameterizedTypeReference<>() {});
BaseDao<Order> orderDao = context.getBean("orderDao", new ParameterizedTypeReference<>() {});
userDao.persist(new User("1"));
orderDao.persist(new Order("2"));