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(); + } }