Browse Source

Reliably refresh metadata for dynamically changing prototype bean class

Closes gh-26019
pull/26044/head
Juergen Hoeller 4 years ago
parent
commit
412aa06d86
  1. 14
      spring-beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java
  2. 55
      spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java

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

@ -26,9 +26,6 @@ import java.util.Collections; @@ -26,9 +26,6 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.support.RootBeanDefinition;
@ -69,8 +66,6 @@ public class InjectionMetadata { @@ -69,8 +66,6 @@ public class InjectionMetadata {
};
private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
private final Class<?> targetClass;
private final Collection<InjectedElement> injectedElements;
@ -110,9 +105,6 @@ public class InjectionMetadata { @@ -110,9 +105,6 @@ public class InjectionMetadata {
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
beanDefinition.registerExternallyManagedConfigMember(member);
checkedElements.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
}
}
}
this.checkedElements = checkedElements;
@ -124,9 +116,6 @@ public class InjectionMetadata { @@ -124,9 +116,6 @@ public class InjectionMetadata {
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
@ -157,7 +146,8 @@ public class InjectionMetadata { @@ -157,7 +146,8 @@ public class InjectionMetadata {
* @since 5.2
*/
public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
return (elements.isEmpty() ? new InjectionMetadata(clazz, Collections.emptyList()) :
new InjectionMetadata(clazz, elements));
}
/**

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

@ -307,6 +307,23 @@ public class ConfigurationClassProcessingTests { @@ -307,6 +307,23 @@ public class ConfigurationClassProcessingTests {
assertThat(tb.getLawyer()).isEqualTo(ctx.getBean(NestedTestBean.class));
}
@Test // gh-26019
public void autowiringWithDynamicPrototypeBeanClass() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
ConfigWithDynamicPrototype.class, PrototypeDependency.class);
PrototypeInterface p1 = ctx.getBean(PrototypeInterface.class, 1);
assertThat(p1).isInstanceOf(PrototypeOne.class);
assertThat(((PrototypeOne) p1).prototypeDependency).isNotNull();
PrototypeInterface p2 = ctx.getBean(PrototypeInterface.class, 2);
assertThat(p2).isInstanceOf(PrototypeTwo.class);
PrototypeInterface p3 = ctx.getBean(PrototypeInterface.class, 1);
assertThat(p3).isInstanceOf(PrototypeOne.class);
assertThat(((PrototypeOne) p3).prototypeDependency).isNotNull();
}
/**
* Creates a new {@link BeanFactory}, populates it with a {@link BeanDefinition}
@ -632,4 +649,42 @@ public class ConfigurationClassProcessingTests { @@ -632,4 +649,42 @@ public class ConfigurationClassProcessingTests {
}
}
static class PrototypeDependency {
}
interface PrototypeInterface {
}
static class PrototypeOne extends AbstractPrototype {
@Autowired
PrototypeDependency prototypeDependency;
}
static class PrototypeTwo extends AbstractPrototype {
// no autowired dependency here, in contrast to above
}
static class AbstractPrototype implements PrototypeInterface {
}
@Configuration
static class ConfigWithDynamicPrototype {
@Bean
@Scope(value = "prototype")
public PrototypeInterface getDemoBean( int i) {
switch ( i) {
case 1: return new PrototypeOne();
case 2:
default:
return new PrototypeTwo();
}
}
}
}

Loading…
Cancel
Save