Skip to content

Commit 161a717

Browse files
committed
Avoid synchronization for shortcut re-resolution
See gh-30883
1 parent 28e63e9 commit 161a717

File tree

2 files changed

+65
-7
lines changed

2 files changed

+65
-7
lines changed

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -832,14 +832,18 @@ private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mb
832832
}
833833
catch (BeansException ex) {
834834
// Unexpected target bean mismatch for cached argument -> re-resolve
835-
synchronized (descriptor) {
836-
if (!descriptor.hasShortcut()) {
837-
throw ex;
838-
}
835+
Set<String> autowiredBeanNames = null;
836+
if (descriptor.hasShortcut()) {
837+
// Reset shortcut and try to re-resolve it in this thread...
839838
descriptor.setShortcut(null);
840-
Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
841-
argValue = resolveAutowiredArgument(descriptor, paramType, beanName,
842-
autowiredBeanNames, converter, true);
839+
autowiredBeanNames = new LinkedHashSet<>(2);
840+
}
841+
logger.debug("Failed to resolve cached argument", ex);
842+
argValue = resolveAutowiredArgument(descriptor, paramType, beanName,
843+
autowiredBeanNames, converter, true);
844+
if (autowiredBeanNames != null && !descriptor.hasShortcut()) {
845+
// We encountered as stale shortcut before, and the shortcut has
846+
// not been re-resolved by another thread in the meantime...
843847
if (argValue != null) {
844848
setShortcutIfPossible(descriptor, paramType, autowiredBeanNames);
845849
}

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,22 @@ void optionalResourceInjectionWithSingletonRemoval() {
423423
assertThat(bean.nestedTestBeansField[1]).isSameAs(ntb2);
424424

425425
bf.destroySingleton("testBean");
426+
bf.registerSingleton("testBeanX", tb);
427+
428+
bean = bf.getBean("annotatedBean", OptionalResourceInjectionBean.class);
429+
assertThat(bean.getTestBean()).isSameAs(tb);
430+
assertThat(bean.getTestBean2()).isSameAs(tb);
431+
assertThat(bean.getTestBean3()).isSameAs(tb);
432+
assertThat(bean.getTestBean4()).isSameAs(tb);
433+
assertThat(bean.getIndexedTestBean()).isSameAs(itb);
434+
assertThat(bean.getNestedTestBeans()).hasSize(2);
435+
assertThat(bean.getNestedTestBeans()[0]).isSameAs(ntb1);
436+
assertThat(bean.getNestedTestBeans()[1]).isSameAs(ntb2);
437+
assertThat(bean.nestedTestBeansField).hasSize(2);
438+
assertThat(bean.nestedTestBeansField[0]).isSameAs(ntb1);
439+
assertThat(bean.nestedTestBeansField[1]).isSameAs(ntb2);
440+
441+
bf.destroySingleton("testBeanX");
426442

427443
bean = bf.getBean("annotatedBean", OptionalResourceInjectionBean.class);
428444
assertThat(bean.getTestBean()).isNull();
@@ -480,6 +496,22 @@ void optionalResourceInjectionWithBeanDefinitionRemoval() {
480496
assertThat(bean.nestedTestBeansField[1]).isSameAs(ntb2);
481497

482498
bf.removeBeanDefinition("testBean");
499+
bf.registerBeanDefinition("testBeanX", new RootBeanDefinition(TestBean.class));
500+
501+
bean = bf.getBean("annotatedBean", OptionalResourceInjectionBean.class);
502+
assertThat(bean.getTestBean()).isSameAs(bf.getBean("testBeanX"));
503+
assertThat(bean.getTestBean2()).isSameAs(bf.getBean("testBeanX"));
504+
assertThat(bean.getTestBean3()).isSameAs(bf.getBean("testBeanX"));
505+
assertThat(bean.getTestBean4()).isSameAs(bf.getBean("testBeanX"));
506+
assertThat(bean.getIndexedTestBean()).isSameAs(itb);
507+
assertThat(bean.getNestedTestBeans()).hasSize(2);
508+
assertThat(bean.getNestedTestBeans()[0]).isSameAs(ntb1);
509+
assertThat(bean.getNestedTestBeans()[1]).isSameAs(ntb2);
510+
assertThat(bean.nestedTestBeansField).hasSize(2);
511+
assertThat(bean.nestedTestBeansField[0]).isSameAs(ntb1);
512+
assertThat(bean.nestedTestBeansField[1]).isSameAs(ntb2);
513+
514+
bf.removeBeanDefinition("testBeanX");
483515

484516
bean = bf.getBean("annotatedBean", OptionalResourceInjectionBean.class);
485517
assertThat(bean.getTestBean()).isNull();
@@ -768,6 +800,17 @@ void constructorResourceInjectionWithSingletonRemoval() {
768800
assertThat(bean.getBeanFactory()).isSameAs(bf);
769801

770802
bf.destroySingleton("nestedTestBean");
803+
bf.registerSingleton("nestedTestBeanX", ntb);
804+
805+
bean = bf.getBean("annotatedBean", ConstructorResourceInjectionBean.class);
806+
assertThat(bean.getTestBean()).isSameAs(tb);
807+
assertThat(bean.getTestBean2()).isSameAs(tb);
808+
assertThat(bean.getTestBean3()).isSameAs(tb);
809+
assertThat(bean.getTestBean4()).isSameAs(tb);
810+
assertThat(bean.getNestedTestBean()).isSameAs(ntb);
811+
assertThat(bean.getBeanFactory()).isSameAs(bf);
812+
813+
bf.destroySingleton("nestedTestBeanX");
771814

772815
bean = bf.getBean("annotatedBean", ConstructorResourceInjectionBean.class);
773816
assertThat(bean.getTestBean()).isSameAs(tb);
@@ -806,6 +849,17 @@ void constructorResourceInjectionWithBeanDefinitionRemoval() {
806849
assertThat(bean.getBeanFactory()).isSameAs(bf);
807850

808851
bf.removeBeanDefinition("nestedTestBean");
852+
bf.registerBeanDefinition("nestedTestBeanX", new RootBeanDefinition(NestedTestBean.class));
853+
854+
bean = bf.getBean("annotatedBean", ConstructorResourceInjectionBean.class);
855+
assertThat(bean.getTestBean()).isSameAs(tb);
856+
assertThat(bean.getTestBean2()).isSameAs(tb);
857+
assertThat(bean.getTestBean3()).isSameAs(tb);
858+
assertThat(bean.getTestBean4()).isSameAs(tb);
859+
assertThat(bean.getNestedTestBean()).isSameAs(bf.getBean("nestedTestBeanX"));
860+
assertThat(bean.getBeanFactory()).isSameAs(bf);
861+
862+
bf.removeBeanDefinition("nestedTestBeanX");
809863

810864
bean = bf.getBean("annotatedBean", ConstructorResourceInjectionBean.class);
811865
assertThat(bean.getTestBean()).isSameAs(tb);

0 commit comments

Comments
 (0)