Support for fine-grained by-type references and autowired properties
Closes gh-23032
This commit is contained in:
parent
eeb79c8dde
commit
859923b732
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -32,6 +32,8 @@ public interface BeanMetadataElement {
|
|||
* (may be {@code null}).
|
||||
*/
|
||||
@Nullable
|
||||
Object getSource();
|
||||
default Object getSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Simple marker class for an individually autowired property value, to be added
|
||||
* to {@link BeanDefinition#getPropertyValues()} for a specific bean property.
|
||||
*
|
||||
* <p>At runtime, this will be replaced with a {@link DependencyDescriptor}
|
||||
* for the corresponding bean property's write method, eventually to be resolved
|
||||
* through a {@link AutowireCapableBeanFactory#resolveDependency} step.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 5.2
|
||||
* @see AutowireCapableBeanFactory#resolveDependency
|
||||
* @see BeanDefinition#getPropertyValues()
|
||||
* @see org.springframework.beans.factory.support.BeanDefinitionBuilder#addAutowiredProperty
|
||||
*/
|
||||
public final class AutowiredPropertyMarker implements Serializable {
|
||||
|
||||
/**
|
||||
* The canonical instance for the autowired marker value.
|
||||
*/
|
||||
public static final Object INSTANCE = new AutowiredPropertyMarker();
|
||||
|
||||
|
||||
private AutowiredPropertyMarker() {
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return (this == obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return AutowiredPropertyMarker.class.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(autowired)";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -26,12 +26,16 @@ import org.springframework.util.Assert;
|
|||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @see BeanDefinition#getPropertyValues()
|
||||
* @see org.springframework.beans.factory.BeanFactory#getBean
|
||||
* @see org.springframework.beans.factory.BeanFactory#getBean(String)
|
||||
* @see org.springframework.beans.factory.BeanFactory#getBean(Class)
|
||||
*/
|
||||
public class RuntimeBeanReference implements BeanReference {
|
||||
|
||||
private final String beanName;
|
||||
|
||||
@Nullable
|
||||
private final Class<?> beanType;
|
||||
|
||||
private final boolean toParent;
|
||||
|
||||
@Nullable
|
||||
|
|
@ -39,9 +43,7 @@ public class RuntimeBeanReference implements BeanReference {
|
|||
|
||||
|
||||
/**
|
||||
* Create a new RuntimeBeanReference to the given bean name,
|
||||
* without explicitly marking it as reference to a bean in
|
||||
* the parent factory.
|
||||
* Create a new RuntimeBeanReference to the given bean name.
|
||||
* @param beanName name of the target bean
|
||||
*/
|
||||
public RuntimeBeanReference(String beanName) {
|
||||
|
|
@ -50,27 +52,64 @@ public class RuntimeBeanReference implements BeanReference {
|
|||
|
||||
/**
|
||||
* Create a new RuntimeBeanReference to the given bean name,
|
||||
* with the option to mark it as reference to a bean in
|
||||
* the parent factory.
|
||||
* with the option to mark it as reference to a bean in the parent factory.
|
||||
* @param beanName name of the target bean
|
||||
* @param toParent whether this is an explicit reference to
|
||||
* a bean in the parent factory
|
||||
* @param toParent whether this is an explicit reference to a bean in the
|
||||
* parent factory
|
||||
*/
|
||||
public RuntimeBeanReference(String beanName, boolean toParent) {
|
||||
Assert.hasText(beanName, "'beanName' must not be empty");
|
||||
this.beanName = beanName;
|
||||
this.beanType = null;
|
||||
this.toParent = toParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new RuntimeBeanReference to a bean of the given type.
|
||||
* @param beanType type of the target bean
|
||||
* @since 5.2
|
||||
*/
|
||||
public RuntimeBeanReference(Class<?> beanType) {
|
||||
this(beanType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new RuntimeBeanReference to a bean of the given type,
|
||||
* with the option to mark it as reference to a bean in the parent factory.
|
||||
* @param beanType type of the target bean
|
||||
* @param toParent whether this is an explicit reference to a bean in the
|
||||
* parent factory
|
||||
* @since 5.2
|
||||
*/
|
||||
public RuntimeBeanReference(Class<?> beanType, boolean toParent) {
|
||||
Assert.notNull(beanType, "'beanType' must not be empty");
|
||||
this.beanName = beanType.getName();
|
||||
this.beanType = beanType;
|
||||
this.toParent = toParent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the requested bean name, or the fully-qualified type name
|
||||
* in case of by-type resolution.
|
||||
* @see #getBeanType()
|
||||
*/
|
||||
@Override
|
||||
public String getBeanName() {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this is an explicit reference to a bean
|
||||
* in the parent factory.
|
||||
* Return the requested bean type if resolution by type is demanded.
|
||||
* @since 5.2
|
||||
*/
|
||||
@Nullable
|
||||
public Class<?> getBeanType() {
|
||||
return this.beanType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this is an explicit reference to a bean in the parent factory.
|
||||
*/
|
||||
public boolean isToParent() {
|
||||
return this.toParent;
|
||||
|
|
@ -100,7 +139,8 @@ public class RuntimeBeanReference implements BeanReference {
|
|||
return false;
|
||||
}
|
||||
RuntimeBeanReference that = (RuntimeBeanReference) other;
|
||||
return (this.beanName.equals(that.beanName) && this.toParent == that.toParent);
|
||||
return (this.beanName.equals(that.beanName) && this.beanType == that.beanType &&
|
||||
this.toParent == that.toParent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ import org.springframework.beans.factory.InitializingBean;
|
|||
import org.springframework.beans.factory.InjectionPoint;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.AutowiredPropertyMarker;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
|
|
@ -1683,6 +1684,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
|||
else {
|
||||
String propertyName = pv.getName();
|
||||
Object originalValue = pv.getValue();
|
||||
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
|
||||
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
|
||||
if (writeMethod == null) {
|
||||
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
|
||||
}
|
||||
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
|
||||
}
|
||||
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
|
||||
Object convertedValue = resolvedValue;
|
||||
boolean convertible = bw.isWritableProperty(propertyName) &&
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.springframework.beans.factory.support;
|
|||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.config.AutowiredPropertyMarker;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
|
@ -209,7 +210,7 @@ public final class BeanDefinitionBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add the supplied property value under the given name.
|
||||
* Add the supplied property value under the given property name.
|
||||
*/
|
||||
public BeanDefinitionBuilder addPropertyValue(String name, @Nullable Object value) {
|
||||
this.beanDefinition.getPropertyValues().add(name, value);
|
||||
|
|
@ -226,6 +227,17 @@ public final class BeanDefinitionBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an autowired marker for the specified property on the specified bean.
|
||||
* @param name the name of the property to mark as autowired
|
||||
* @since 5.2
|
||||
* @see AutowiredPropertyMarker
|
||||
*/
|
||||
public BeanDefinitionBuilder addAutowiredProperty(String name) {
|
||||
this.beanDefinition.getPropertyValues().add(name, AutowiredPropertyMarker.INSTANCE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the init method for this definition.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -30,10 +30,13 @@ import org.springframework.beans.BeansException;
|
|||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.NamedBeanHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanNameReference;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
|
|
@ -57,7 +60,7 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
class BeanDefinitionValueResolver {
|
||||
|
||||
private final AbstractBeanFactory beanFactory;
|
||||
private final AbstractAutowireCapableBeanFactory beanFactory;
|
||||
|
||||
private final String beanName;
|
||||
|
||||
|
|
@ -73,8 +76,8 @@ class BeanDefinitionValueResolver {
|
|||
* @param beanDefinition the BeanDefinition of the bean that we work on
|
||||
* @param typeConverter the TypeConverter to use for resolving TypedStringValues
|
||||
*/
|
||||
public BeanDefinitionValueResolver(
|
||||
AbstractBeanFactory beanFactory, String beanName, BeanDefinition beanDefinition, TypeConverter typeConverter) {
|
||||
public BeanDefinitionValueResolver(AbstractAutowireCapableBeanFactory beanFactory, String beanName,
|
||||
BeanDefinition beanDefinition, TypeConverter typeConverter) {
|
||||
|
||||
this.beanFactory = beanFactory;
|
||||
this.beanName = beanName;
|
||||
|
|
@ -130,6 +133,17 @@ class BeanDefinitionValueResolver {
|
|||
ObjectUtils.getIdentityHexString(bd);
|
||||
return resolveInnerBean(argName, innerBeanName, bd);
|
||||
}
|
||||
else if (value instanceof DependencyDescriptor) {
|
||||
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
|
||||
Object result = this.beanFactory.resolveDependency(
|
||||
(DependencyDescriptor) value, this.beanName, autowiredBeanNames, this.typeConverter);
|
||||
for (String autowiredBeanName : autowiredBeanNames) {
|
||||
if (this.beanFactory.containsBean(autowiredBeanName)) {
|
||||
this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (value instanceof ManagedArray) {
|
||||
// May need to resolve contained runtime references.
|
||||
ManagedArray array = (ManagedArray) value;
|
||||
|
|
@ -281,6 +295,54 @@ class BeanDefinitionValueResolver {
|
|||
return value.resolveTargetType(this.beanFactory.getBeanClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a reference to another bean in the factory.
|
||||
*/
|
||||
@Nullable
|
||||
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
|
||||
try {
|
||||
Object bean;
|
||||
Class<?> beanType = ref.getBeanType();
|
||||
if (ref.isToParent()) {
|
||||
BeanFactory parent = this.beanFactory.getParentBeanFactory();
|
||||
if (parent == null) {
|
||||
throw new BeanCreationException(
|
||||
this.beanDefinition.getResourceDescription(), this.beanName,
|
||||
"Cannot resolve reference to bean " + ref +
|
||||
" in parent factory: no parent factory available");
|
||||
}
|
||||
if (beanType != null) {
|
||||
bean = parent.getBean(beanType);
|
||||
}
|
||||
else {
|
||||
bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
|
||||
}
|
||||
}
|
||||
else {
|
||||
String resolvedName;
|
||||
if (beanType != null) {
|
||||
NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
|
||||
bean = namedBean.getBeanInstance();
|
||||
resolvedName = namedBean.getBeanName();
|
||||
}
|
||||
else {
|
||||
resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
|
||||
bean = this.beanFactory.getBean(resolvedName);
|
||||
}
|
||||
this.beanFactory.registerDependentBean(resolvedName, this.beanName);
|
||||
}
|
||||
if (bean instanceof NullBean) {
|
||||
bean = null;
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
catch (BeansException ex) {
|
||||
throw new BeanCreationException(
|
||||
this.beanDefinition.getResourceDescription(), this.beanName,
|
||||
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve an inner bean definition.
|
||||
* @param argName the name of the argument that the inner bean is defined for
|
||||
|
|
@ -345,48 +407,13 @@ class BeanDefinitionValueResolver {
|
|||
return actualInnerBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a reference to another bean in the factory.
|
||||
*/
|
||||
@Nullable
|
||||
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
|
||||
try {
|
||||
Object bean;
|
||||
String refName = ref.getBeanName();
|
||||
refName = String.valueOf(doEvaluate(refName));
|
||||
if (ref.isToParent()) {
|
||||
if (this.beanFactory.getParentBeanFactory() == null) {
|
||||
throw new BeanCreationException(
|
||||
this.beanDefinition.getResourceDescription(), this.beanName,
|
||||
"Can't resolve reference to bean '" + refName +
|
||||
"' in parent factory: no parent factory available");
|
||||
}
|
||||
bean = this.beanFactory.getParentBeanFactory().getBean(refName);
|
||||
}
|
||||
else {
|
||||
bean = this.beanFactory.getBean(refName);
|
||||
this.beanFactory.registerDependentBean(refName, this.beanName);
|
||||
}
|
||||
if (bean instanceof NullBean) {
|
||||
bean = null;
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
catch (BeansException ex) {
|
||||
throw new BeanCreationException(
|
||||
this.beanDefinition.getResourceDescription(), this.beanName,
|
||||
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For each element in the managed array, resolve reference if necessary.
|
||||
*/
|
||||
private Object resolveManagedArray(Object argName, List<?> ml, Class<?> elementType) {
|
||||
Object resolved = Array.newInstance(elementType, ml.size());
|
||||
for (int i = 0; i < ml.size(); i++) {
|
||||
Array.set(resolved, i,
|
||||
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
|
||||
Array.set(resolved, i, resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
|
@ -397,8 +424,7 @@ class BeanDefinitionValueResolver {
|
|||
private List<?> resolveManagedList(Object argName, List<?> ml) {
|
||||
List<Object> resolved = new ArrayList<>(ml.size());
|
||||
for (int i = 0; i < ml.size(); i++) {
|
||||
resolved.add(
|
||||
resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
|
||||
resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import org.springframework.beans.PropertyValue;
|
|||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.AutowiredPropertyMarker;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
||||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||
|
|
@ -575,10 +576,94 @@ public class DefaultListableBeanFactoryTests {
|
|||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setPropertyValues(pvs);
|
||||
lbf.registerBeanDefinition("self", bd);
|
||||
|
||||
TestBean self = (TestBean) lbf.getBean("self");
|
||||
assertThat(self.getSpouse()).isEqualTo(self);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferenceByName() {
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("doctor", new RuntimeBeanReference("doc"));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setPropertyValues(pvs);
|
||||
lbf.registerBeanDefinition("self", bd);
|
||||
lbf.registerBeanDefinition("doc", new RootBeanDefinition(NestedTestBean.class));
|
||||
|
||||
TestBean self = (TestBean) lbf.getBean("self");
|
||||
assertThat(self.getDoctor()).isEqualTo(lbf.getBean("doc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferenceByType() {
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("doctor", new RuntimeBeanReference(NestedTestBean.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setPropertyValues(pvs);
|
||||
lbf.registerBeanDefinition("self", bd);
|
||||
lbf.registerBeanDefinition("doc", new RootBeanDefinition(NestedTestBean.class));
|
||||
|
||||
TestBean self = (TestBean) lbf.getBean("self");
|
||||
assertThat(self.getDoctor()).isEqualTo(lbf.getBean("doc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferenceByAutowire() {
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("doctor", AutowiredPropertyMarker.INSTANCE);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setPropertyValues(pvs);
|
||||
lbf.registerBeanDefinition("self", bd);
|
||||
lbf.registerBeanDefinition("doc", new RootBeanDefinition(NestedTestBean.class));
|
||||
|
||||
TestBean self = (TestBean) lbf.getBean("self");
|
||||
assertThat(self.getDoctor()).isEqualTo(lbf.getBean("doc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayReferenceByName() {
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("stringArray", new RuntimeBeanReference("string"));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setPropertyValues(pvs);
|
||||
lbf.registerBeanDefinition("self", bd);
|
||||
lbf.registerSingleton("string", "A");
|
||||
|
||||
TestBean self = (TestBean) lbf.getBean("self");
|
||||
assertThat(self.getStringArray()).hasSize(1);
|
||||
assertThat(self.getStringArray()).contains("A");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayReferenceByType() {
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("stringArray", new RuntimeBeanReference(String.class));
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setPropertyValues(pvs);
|
||||
lbf.registerBeanDefinition("self", bd);
|
||||
lbf.registerSingleton("string", "A");
|
||||
|
||||
TestBean self = (TestBean) lbf.getBean("self");
|
||||
assertThat(self.getStringArray()).hasSize(1);
|
||||
assertThat(self.getStringArray()).contains("A");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayReferenceByAutowire() {
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
pvs.add("stringArray", AutowiredPropertyMarker.INSTANCE);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setPropertyValues(pvs);
|
||||
lbf.registerBeanDefinition("self", bd);
|
||||
lbf.registerSingleton("string1", "A");
|
||||
lbf.registerSingleton("string2", "B");
|
||||
|
||||
TestBean self = (TestBean) lbf.getBean("self");
|
||||
assertThat(self.getStringArray()).hasSize(2);
|
||||
assertThat(self.getStringArray()).contains("A");
|
||||
assertThat(self.getStringArray()).contains("B");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPossibleMatches() {
|
||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||
|
|
@ -586,6 +671,7 @@ public class DefaultListableBeanFactoryTests {
|
|||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.setPropertyValues(pvs);
|
||||
lbf.registerBeanDefinition("tb", bd);
|
||||
|
||||
assertThatExceptionOfType(BeanCreationException.class).as("invalid property").isThrownBy(() ->
|
||||
lbf.getBean("tb"))
|
||||
.withCauseInstanceOf(NotWritablePropertyException.class)
|
||||
|
|
|
|||
Loading…
Reference in New Issue