Skip to content

Commit aa56b50

Browse files
committed
Detect late-set primary markers for autowiring shortcut algorithm
Closes gh-34658
1 parent 84430a8 commit aa56b50

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -1474,7 +1474,7 @@ protected RootBeanDefinition getMergedBeanDefinition(
14741474
// Cache the merged bean definition for the time being
14751475
// (it might still get re-merged later on in order to pick up metadata changes)
14761476
if (containingBd == null && (isCacheBeanMetadata() || isBeanEligibleForMetadataCaching(beanName))) {
1477-
this.mergedBeanDefinitions.put(beanName, mbd);
1477+
cacheMergedBeanDefinition(mbd, beanName);
14781478
}
14791479
}
14801480
if (previous != null) {
@@ -1503,6 +1503,18 @@ private void copyRelevantMergedBeanDefinitionCaches(RootBeanDefinition previous,
15031503
}
15041504
}
15051505

1506+
/**
1507+
* Cache the given merged bean definition.
1508+
* <p>Subclasses can override this to derive additional cached state
1509+
* from the final post-processed bean definition.
1510+
* @param mbd the merged bean definition to cache
1511+
* @param beanName the name of the bean
1512+
* @since 6.2.6
1513+
*/
1514+
protected void cacheMergedBeanDefinition(RootBeanDefinition mbd, String beanName) {
1515+
this.mergedBeanDefinitions.put(beanName, mbd);
1516+
}
1517+
15061518
/**
15071519
* Check the given merged bean definition,
15081520
* potentially throwing validation exceptions.

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

+8
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,14 @@ protected Object obtainInstanceFromSupplier(Supplier<?> supplier, String beanNam
10191019
return super.obtainInstanceFromSupplier(supplier, beanName, mbd);
10201020
}
10211021

1022+
@Override
1023+
protected void cacheMergedBeanDefinition(RootBeanDefinition mbd, String beanName) {
1024+
super.cacheMergedBeanDefinition(mbd, beanName);
1025+
if (mbd.isPrimary()) {
1026+
this.primaryBeanNames.add(beanName);
1027+
}
1028+
}
1029+
10221030
@Override
10231031
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args) {
10241032
super.checkMergedBeanDefinition(mbd, beanName, args);

spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java

+34
Original file line numberDiff line numberDiff line change
@@ -1727,6 +1727,40 @@ void objectProviderInjectionWithTargetPrimary() {
17271727
tb2.setFactoryMethodName("newTestBean2");
17281728
tb2.setLazyInit(true);
17291729
bf.registerBeanDefinition("testBean2", tb2);
1730+
bf.registerAlias("testBean2", "testBean");
1731+
1732+
ObjectProviderInjectionBean bean = bf.getBean("annotatedBean", ObjectProviderInjectionBean.class);
1733+
TestBean testBean1 = bf.getBean("testBean1", TestBean.class);
1734+
assertThat(bean.getTestBean()).isSameAs(testBean1);
1735+
assertThat(bean.getOptionalTestBean()).isSameAs(testBean1);
1736+
assertThat(bean.consumeOptionalTestBean()).isSameAs(testBean1);
1737+
assertThat(bean.getUniqueTestBean()).isSameAs(testBean1);
1738+
assertThat(bean.consumeUniqueTestBean()).isSameAs(testBean1);
1739+
assertThat(bf.containsSingleton("testBean2")).isFalse();
1740+
1741+
TestBean testBean2 = bf.getBean("testBean2", TestBean.class);
1742+
assertThat(bean.iterateTestBeans()).containsExactly(testBean1, testBean2);
1743+
assertThat(bean.forEachTestBeans()).containsExactly(testBean1, testBean2);
1744+
assertThat(bean.streamTestBeans()).containsExactly(testBean1, testBean2);
1745+
assertThat(bean.streamTestBeansInOrder()).containsExactly(testBean2, testBean1);
1746+
assertThat(bean.allTestBeans()).containsExactly(testBean1, testBean2);
1747+
assertThat(bean.allTestBeansInOrder()).containsExactly(testBean2, testBean1);
1748+
assertThat(bean.allSingletonBeans()).containsExactly(testBean1, testBean2);
1749+
assertThat(bean.allSingletonBeansInOrder()).containsExactly(testBean2, testBean1);
1750+
}
1751+
1752+
@Test
1753+
void objectProviderInjectionWithLateMarkedTargetPrimary() {
1754+
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ObjectProviderInjectionBean.class));
1755+
RootBeanDefinition tb1 = new RootBeanDefinition(TestBeanFactory.class);
1756+
tb1.setFactoryMethodName("newTestBean1");
1757+
bf.registerBeanDefinition("testBean1", tb1);
1758+
RootBeanDefinition tb2 = new RootBeanDefinition(TestBeanFactory.class);
1759+
tb2.setFactoryMethodName("newTestBean2");
1760+
tb2.setLazyInit(true);
1761+
bf.registerBeanDefinition("testBean2", tb2);
1762+
bf.registerAlias("testBean2", "testBean");
1763+
tb1.setPrimary(true);
17301764

17311765
ObjectProviderInjectionBean bean = bf.getBean("annotatedBean", ObjectProviderInjectionBean.class);
17321766
TestBean testBean1 = bf.getBean("testBean1", TestBean.class);

0 commit comments

Comments
 (0)