From c1b1b2fec8d9bc20b128b5df96646e51ec28f39b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sch=C3=A4fer=2C=20H=2EH=2E=20=28Hans=20Hosea=29?= Date: Mon, 13 Oct 2025 22:46:55 +0200 Subject: [PATCH] 35626: defaultCandidate for scoped proxies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Schäfer, H.H. (Hans Hosea) --- .../aop/scope/ScopedProxyUtils.java | 4 + .../aop/scope/ScopedProxyUtilsTests.java | 73 +++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyUtils.java b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyUtils.java index f6715a15d15d..004012b0123d 100644 --- a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyUtils.java +++ b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyUtils.java @@ -83,11 +83,15 @@ public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder defini proxyDefinition.setPrimary(targetDefinition.isPrimary()); if (targetDefinition instanceof AbstractBeanDefinition abd) { proxyDefinition.copyQualifiersFrom(abd); + proxyDefinition.setDefaultCandidate(abd.isDefaultCandidate()); } // The target bean should be ignored in favor of the scoped proxy. targetDefinition.setAutowireCandidate(false); targetDefinition.setPrimary(false); + if (targetDefinition instanceof AbstractBeanDefinition abd) { + abd.setDefaultCandidate(false); + } // Register the target bean as separate bean in the factory. registry.registerBeanDefinition(targetBeanName, targetDefinition); diff --git a/spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyUtilsTests.java b/spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyUtilsTests.java index ff3299cd4a50..164e6c85216b 100644 --- a/spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyUtilsTests.java +++ b/spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyUtilsTests.java @@ -18,9 +18,19 @@ import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.AutowireCandidateQualifier; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + /** * Tests for {@link ScopedProxyUtils}. * @@ -64,4 +74,67 @@ void getOriginalBeanNameForNonScopedTarget() { .withMessage("bean name 'myBean' does not refer to the target of a scoped proxy"); } + @Test + void createScopedProxyTargetOvertakesAutowireSettingsToProxyBeanDefinition() { + final AbstractBeanDefinition targetDefinition = new GenericBeanDefinition(); + // Opposite of defaults + targetDefinition.setAutowireCandidate(false); + targetDefinition.setDefaultCandidate(false); + targetDefinition.setPrimary(true); + + final BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); + final BeanDefinitionHolder proxyHolder = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(targetDefinition, "myBean"), registry, false); + assertThat(proxyHolder).isNotNull(); + final BeanDefinition proxyBeanDefinition = proxyHolder.getBeanDefinition(); + assertThat(proxyBeanDefinition).isNotNull(); + assertThat(proxyBeanDefinition).isInstanceOf(RootBeanDefinition.class); + + assertThat(proxyBeanDefinition.isAutowireCandidate()).isFalse(); + assertThat(proxyBeanDefinition.isPrimary()).isTrue(); + assertThat(((RootBeanDefinition)proxyBeanDefinition).isDefaultCandidate()).isFalse(); + } + + @Test + void createScopedProxyTargetOvertakesBeanAttributesToProxyBeanDefinition() { + final GenericBeanDefinition targetDefinition = new GenericBeanDefinition(); + // Opposite of defaults + targetDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + targetDefinition.setSource("theSource"); + targetDefinition.addQualifier(new AutowireCandidateQualifier("myQualifier")); + + final BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); + final BeanDefinitionHolder proxyHolder = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(targetDefinition, "myBean"), registry, false); + assertThat(proxyHolder).isNotNull(); + final BeanDefinition proxyBeanDefinition = proxyHolder.getBeanDefinition(); + assertThat(proxyBeanDefinition).isNotNull(); + + assertThat(proxyBeanDefinition.getRole()).isEqualTo(BeanDefinition.ROLE_INFRASTRUCTURE); + assertThat(proxyBeanDefinition).isInstanceOf(RootBeanDefinition.class); + assertThat(proxyBeanDefinition.getPropertyValues()).hasSize(2); + assertThat(proxyBeanDefinition.getPropertyValues().get("proxyTargetClass")).isEqualTo(false); + assertThat(proxyBeanDefinition.getPropertyValues().get("targetBeanName")).isEqualTo(ScopedProxyUtils.getTargetBeanName("myBean")); + + final RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) proxyBeanDefinition; + assertThat(rootBeanDefinition.getQualifiers()).hasSize(1); + assertThat(rootBeanDefinition.hasQualifier("myQualifier")).isTrue(); + assertThat(rootBeanDefinition.getSource()).isEqualTo("theSource"); + } + + @Test + void createScopedProxyTargetCleansAutowireSettingsInTargetDefinition() { + final AbstractBeanDefinition targetDefinition = new GenericBeanDefinition(); + targetDefinition.setAutowireCandidate(true); + targetDefinition.setDefaultCandidate(true); + targetDefinition.setPrimary(true); + + final BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); + final BeanDefinitionHolder proxyHolder = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(targetDefinition, "myBean"), registry, false); + assertThat(proxyHolder).isNotNull(); + final BeanDefinition proxyBeanDefinition = proxyHolder.getBeanDefinition(); + assertThat(proxyBeanDefinition).isNotNull(); + + assertThat(targetDefinition.isAutowireCandidate()).isFalse(); + assertThat(targetDefinition.isDefaultCandidate()).isFalse(); + assertThat(targetDefinition.isPrimary()).isFalse(); + } }