From 6b6cf1b4a2f8b03693876dd7b534b49c48a288bd Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 19 Oct 2022 09:55:47 +0200 Subject: [PATCH] Avoid decorated definition bypass for scoped proxy determination GenericApplicationContext registers proxy hints without any SmartInstantiationAwareBeanPostProcessor involved as well. Closes gh-29335 --- .../factory/support/AbstractBeanFactory.java | 44 ++++++++++--------- .../support/GenericApplicationContext.java | 35 +++++++++------ 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java index 50a4e620c6..509ef10f06 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java @@ -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 diff --git a/spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java b/spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java index 8f8f5f64ab..c3daaaf676 100644 --- a/spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java +++ b/spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java @@ -439,29 +439,38 @@ public class GenericApplicationContext extends AbstractApplicationContext implem List 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