Avoid decorated definition bypass for scoped proxy determination

GenericApplicationContext registers proxy hints without any SmartInstantiationAwareBeanPostProcessor involved as well.

Closes gh-29335
This commit is contained in:
Juergen Hoeller 2022-10-19 09:55:47 +02:00
parent 5dca43ebd6
commit 6b6cf1b4a2
2 changed files with 45 additions and 34 deletions

View File

@ -689,33 +689,35 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Check decorated bean definition, if any: We assume it'll be easier
// to determine the decorated bean's type than the proxy's type.
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd);
if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
return targetClass;
}
}
Class<?> beanClass = predictBeanType(beanName, mbd);
// Check bean class whether we're dealing with a FactoryBean.
if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
if (!BeanFactoryUtils.isFactoryDereference(name)) {
// If it's a FactoryBean, we want to look at what it creates, not at the factory class.
return getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit).resolve();
if (beanClass != null) {
// Check bean class whether we're dealing with a FactoryBean.
if (FactoryBean.class.isAssignableFrom(beanClass)) {
if (!BeanFactoryUtils.isFactoryDereference(name)) {
// If it's a FactoryBean, we want to look at what it creates, not at the factory class.
beanClass = getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit).resolve();
}
}
else {
return beanClass;
else if (BeanFactoryUtils.isFactoryDereference(name)) {
return null;
}
}
else {
return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass : null);
if (beanClass == null) {
// Check decorated bean definition, if any: We assume it'll be easier
// to determine the decorated bean's type than the proxy's type.
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd);
if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) {
return targetClass;
}
}
}
return beanClass;
}
@Override

View File

@ -439,29 +439,38 @@ public class GenericApplicationContext extends AbstractApplicationContext implem
List<SmartInstantiationAwareBeanPostProcessor> bpps =
PostProcessorRegistrationDelegate.loadBeanPostProcessors(
this.beanFactory, SmartInstantiationAwareBeanPostProcessor.class);
for (String beanName : this.beanFactory.getBeanDefinitionNames()) {
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType != null) {
registerProxyHintIfNecessary(beanType, runtimeHints);
for (SmartInstantiationAwareBeanPostProcessor bpp : bpps) {
beanType = bpp.determineBeanType(beanType, beanName);
if (Proxy.isProxyClass(beanType)) {
// A JDK proxy class needs an explicit hint
runtimeHints.proxies().registerJdkProxy(beanType.getInterfaces());
}
else {
// Potentially a CGLIB-generated subclass with reflection hints
Class<?> userClass = ClassUtils.getUserClass(beanType);
if (userClass != beanType) {
runtimeHints.reflection()
.registerType(beanType, asClassBasedProxy)
.registerType(userClass, asProxiedUserClass);
}
Class<?> newBeanType = bpp.determineBeanType(beanType, beanName);
if (newBeanType != beanType) {
registerProxyHintIfNecessary(newBeanType, runtimeHints);
beanType = newBeanType;
}
}
}
}
}
private void registerProxyHintIfNecessary(Class<?> beanType, RuntimeHints runtimeHints) {
if (Proxy.isProxyClass(beanType)) {
// A JDK proxy class needs an explicit hint
runtimeHints.proxies().registerJdkProxy(beanType.getInterfaces());
}
else {
// Potentially a CGLIB-generated subclass with reflection hints
Class<?> userClass = ClassUtils.getUserClass(beanType);
if (userClass != beanType) {
runtimeHints.reflection()
.registerType(beanType, asClassBasedProxy)
.registerType(userClass, asProxiedUserClass);
}
}
}
//---------------------------------------------------------------------
// Convenient methods for registering individual beans