Skip to content

Commit 10bff05

Browse files
committed
Reliably refresh metadata for dynamically changing prototype bean class
Closes gh-26019 (cherry picked from commit 412aa06)
1 parent e713e0d commit 10bff05

File tree

2 files changed

+57
-12
lines changed

2 files changed

+57
-12
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@
2626
import java.util.LinkedHashSet;
2727
import java.util.Set;
2828

29-
import org.apache.commons.logging.Log;
30-
import org.apache.commons.logging.LogFactory;
31-
3229
import org.springframework.beans.MutablePropertyValues;
3330
import org.springframework.beans.PropertyValues;
3431
import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -69,8 +66,6 @@ public void clear(@Nullable PropertyValues pvs) {
6966
};
7067

7168

72-
private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
73-
7469
private final Class<?> targetClass;
7570

7671
private final Collection<InjectedElement> injectedElements;
@@ -110,9 +105,6 @@ public void checkConfigMembers(RootBeanDefinition beanDefinition) {
110105
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
111106
beanDefinition.registerExternallyManagedConfigMember(member);
112107
checkedElements.add(element);
113-
if (logger.isTraceEnabled()) {
114-
logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
115-
}
116108
}
117109
}
118110
this.checkedElements = checkedElements;
@@ -124,9 +116,6 @@ public void inject(Object target, @Nullable String beanName, @Nullable PropertyV
124116
(checkedElements != null ? checkedElements : this.injectedElements);
125117
if (!elementsToIterate.isEmpty()) {
126118
for (InjectedElement element : elementsToIterate) {
127-
if (logger.isTraceEnabled()) {
128-
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
129-
}
130119
element.inject(target, beanName, pvs);
131120
}
132121
}
@@ -157,7 +146,8 @@ public void clear(@Nullable PropertyValues pvs) {
157146
* @since 5.2
158147
*/
159148
public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
160-
return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
149+
return (elements.isEmpty() ? new InjectionMetadata(clazz, Collections.emptyList()) :
150+
new InjectionMetadata(clazz, elements));
161151
}
162152

163153
/**

spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,23 @@ public void configurationWithOverloadedBeanMismatchWithAsm() {
307307
assertThat(tb.getLawyer()).isEqualTo(ctx.getBean(NestedTestBean.class));
308308
}
309309

310+
@Test // gh-26019
311+
public void autowiringWithDynamicPrototypeBeanClass() {
312+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
313+
ConfigWithDynamicPrototype.class, PrototypeDependency.class);
314+
315+
PrototypeInterface p1 = ctx.getBean(PrototypeInterface.class, 1);
316+
assertThat(p1).isInstanceOf(PrototypeOne.class);
317+
assertThat(((PrototypeOne) p1).prototypeDependency).isNotNull();
318+
319+
PrototypeInterface p2 = ctx.getBean(PrototypeInterface.class, 2);
320+
assertThat(p2).isInstanceOf(PrototypeTwo.class);
321+
322+
PrototypeInterface p3 = ctx.getBean(PrototypeInterface.class, 1);
323+
assertThat(p3).isInstanceOf(PrototypeOne.class);
324+
assertThat(((PrototypeOne) p3).prototypeDependency).isNotNull();
325+
}
326+
310327

311328
/**
312329
* Creates a new {@link BeanFactory}, populates it with a {@link BeanDefinition}
@@ -632,4 +649,42 @@ public TestBean foo(@Qualifier("other") NestedTestBean other) {
632649
}
633650
}
634651

652+
653+
static class PrototypeDependency {
654+
}
655+
656+
interface PrototypeInterface {
657+
}
658+
659+
static class PrototypeOne extends AbstractPrototype {
660+
661+
@Autowired
662+
PrototypeDependency prototypeDependency;
663+
664+
}
665+
666+
static class PrototypeTwo extends AbstractPrototype {
667+
668+
// no autowired dependency here, in contrast to above
669+
}
670+
671+
static class AbstractPrototype implements PrototypeInterface {
672+
}
673+
674+
@Configuration
675+
static class ConfigWithDynamicPrototype {
676+
677+
@Bean
678+
@Scope(value = "prototype")
679+
public PrototypeInterface getDemoBean( int i) {
680+
switch ( i) {
681+
case 1: return new PrototypeOne();
682+
case 2:
683+
default:
684+
return new PrototypeTwo();
685+
686+
}
687+
}
688+
}
689+
635690
}

0 commit comments

Comments
 (0)