Don't consider singleton instances when deducing bean class

Update `RegisteredBean` bean class detection to not consider
singletons. Prior to this commit, any beans that had been instantiated
could return the wrong class, especially if they were implemented using
a lambda.

See gh-28414
This commit is contained in:
Phillip Webb 2022-05-06 09:51:16 -07:00
parent 2b65f274dc
commit 7700570253
2 changed files with 11 additions and 16 deletions

View File

@ -158,9 +158,6 @@ public final class RegisteredBean {
* @return the bean class * @return the bean class
*/ */
public Class<?> getBeanClass() { public Class<?> getBeanClass() {
if (this.beanFactory.containsSingleton(getBeanName())) {
return this.beanFactory.getSingleton(getBeanName()).getClass();
}
return ClassUtils.getUserClass(getBeanType().toClass()); return ClassUtils.getUserClass(getBeanType().toClass());
} }
@ -169,10 +166,6 @@ public final class RegisteredBean {
* @return the bean type * @return the bean type
*/ */
public ResolvableType getBeanType() { public ResolvableType getBeanType() {
if (this.beanFactory.containsSingleton(getBeanName())) {
return ResolvableType
.forInstance(this.beanFactory.getSingleton(getBeanName()));
}
return getMergedBeanDefinition().getResolvableType(); return getMergedBeanDefinition().getResolvableType();
} }

View File

@ -21,6 +21,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -112,12 +113,6 @@ class RegisteredBeanTests {
assertThat(registeredBean.getBeanClass()).isEqualTo(TestBean.class); assertThat(registeredBean.getBeanClass()).isEqualTo(TestBean.class);
} }
@Test
void getBeanClassWhenSingletonReturnsBeanClass() {
RegisteredBean registeredBean = RegisteredBean.of(this.beanFactory, "sb");
assertThat(registeredBean.getBeanClass()).isEqualTo(TestBean.class);
}
@Test @Test
void getBeanTypeReturnsBeanType() { void getBeanTypeReturnsBeanType() {
RegisteredBean registeredBean = RegisteredBean.of(this.beanFactory, "bd"); RegisteredBean registeredBean = RegisteredBean.of(this.beanFactory, "bd");
@ -125,9 +120,16 @@ class RegisteredBeanTests {
} }
@Test @Test
void getBeanTypeWhenSingletonReturnsBeanType() { void getBeanTypeWhenHasInstanceBackedByLambdaDoesNotReturnLambdaType() {
RegisteredBean registeredBean = RegisteredBean.of(this.beanFactory, "sb"); this.beanFactory.registerBeanDefinition("bfpp", new RootBeanDefinition(
assertThat(registeredBean.getBeanType().toClass()).isEqualTo(TestBean.class); BeanFactoryPostProcessor.class, RegisteredBeanTests::getBeanFactoryPostProcessorLambda));
this.beanFactory.getBean("bfpp");
RegisteredBean registeredBean = RegisteredBean.of(this.beanFactory, "bfpp");
assertThat(registeredBean.getBeanType().toClass()).isEqualTo(BeanFactoryPostProcessor.class);
}
static BeanFactoryPostProcessor getBeanFactoryPostProcessorLambda() {
return bf -> {};
} }
@Test @Test