storing type information as specified (SPR-5556, SPR-5562); explicit XML array element in spring-beans-3.0.xsd (SPR-5543)

This commit is contained in:
Juergen Hoeller 2009-04-15 22:27:32 +00:00
parent 5a561bcd07
commit 1b5812da20
17 changed files with 1568 additions and 202 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -42,6 +42,8 @@ public class TypedStringValue implements BeanMetadataElement {
private Object source; private Object source;
private String specifiedTypeName;
/** /**
* Create a new {@link TypedStringValue} for the given String value. * Create a new {@link TypedStringValue} for the given String value.
@ -169,6 +171,20 @@ public class TypedStringValue implements BeanMetadataElement {
return this.source; return this.source;
} }
/**
* Set the type name as actually specified for this particular value, if any.
*/
public void setSpecifiedTypeName(String specifiedTypeName) {
this.specifiedTypeName = specifiedTypeName;
}
/**
* Return the type name as actually specified for this particular value, if any.
*/
public String getSpecifiedTypeName() {
return this.specifiedTypeName;
}
@Override @Override
public boolean equals(Object other) { public boolean equals(Object other) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
package org.springframework.beans.factory.support; package org.springframework.beans.factory.support;
import java.lang.reflect.Array;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -36,6 +37,8 @@ import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanNameReference; import org.springframework.beans.factory.config.RuntimeBeanNameReference;
import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/** /**
* Helper class for use in bean factory implementations, * Helper class for use in bean factory implementations,
@ -121,6 +124,30 @@ class BeanDefinitionValueResolver {
BeanDefinition bd = (BeanDefinition) value; BeanDefinition bd = (BeanDefinition) value;
return resolveInnerBean(argName, "(inner bean)", bd); return resolveInnerBean(argName, "(inner bean)", bd);
} }
else if (value instanceof ManagedArray) {
// May need to resolve contained runtime references.
ManagedArray array = (ManagedArray) value;
Class elementType = array.resolvedElementType;
if (elementType == null) {
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
else {
elementType = Object.class;
}
}
return resolveManagedArray(argName, (List<?>) value, elementType);
}
else if (value instanceof ManagedList) { else if (value instanceof ManagedList) {
// May need to resolve contained runtime references. // May need to resolve contained runtime references.
return resolveManagedList(argName, (List<?>) value); return resolveManagedList(argName, (List<?>) value);
@ -292,7 +319,21 @@ class BeanDefinitionValueResolver {
} }
/** /**
* For each element in the ManagedList, resolve reference if necessary. * 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(
argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + i + BeanWrapper.PROPERTY_KEY_SUFFIX,
ml.get(i)));
}
return resolved;
}
/**
* For each element in the managed list, resolve reference if necessary.
*/ */
private List resolveManagedList(Object argName, List<?> ml) { private List resolveManagedList(Object argName, List<?> ml) {
List<Object> resolved = new ArrayList<Object>(ml.size()); List<Object> resolved = new ArrayList<Object>(ml.size());
@ -306,7 +347,7 @@ class BeanDefinitionValueResolver {
} }
/** /**
* For each element in the ManagedList, resolve reference if necessary. * For each element in the managed set, resolve reference if necessary.
*/ */
private Set resolveManagedSet(Object argName, Set<?> ms) { private Set resolveManagedSet(Object argName, Set<?> ms) {
Set<Object> resolved = new LinkedHashSet<Object>(ms.size()); Set<Object> resolved = new LinkedHashSet<Object>(ms.size());
@ -320,7 +361,7 @@ class BeanDefinitionValueResolver {
} }
/** /**
* For each element in the ManagedMap, resolve reference if necessary. * For each element in the managed map, resolve reference if necessary.
*/ */
private Map resolveManagedMap(Object argName, Map<?, ?> mm) { private Map resolveManagedMap(Object argName, Map<?, ?> mm) {
Map<Object, Object> resolved = new LinkedHashMap<Object, Object>(mm.size()); Map<Object, Object> resolved = new LinkedHashMap<Object, Object>(mm.size());

View File

@ -744,7 +744,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
* Determine the primary autowire candidate in the given set of beans. * Determine the primary autowire candidate in the given set of beans.
* @param candidateBeans a Map of candidate names and candidate instances * @param candidateBeans a Map of candidate names and candidate instances
* that match the required type, as returned by {@link #findAutowireCandidates} * that match the required type, as returned by {@link #findAutowireCandidates}
* @param type the required type * @param descriptor the target dependency to match against
* @return the name of the primary candidate, or <code>null</code> if none found * @return the name of the primary candidate, or <code>null</code> if none found
*/ */
protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) { protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {

View File

@ -0,0 +1,45 @@
/*
* Copyright 2002-2009 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
*
* http://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.support;
import org.springframework.util.Assert;
/**
* Tag collection class used to hold managed array elements, which may
* include runtime bean references (to be resolved into bean objects).
*
* @author Juergen Hoeller
* @since 3.0
*/
public class ManagedArray extends ManagedList<Object> {
/** Resolved element type for runtime creation of the target array */
volatile Class resolvedElementType;
/**
* Create a new managed array placeholder.
* @param elementTypeName the target element type as a class name
* @param size the size of the array
*/
public ManagedArray(String elementTypeName, int size) {
super(size);
Assert.notNull(elementTypeName, "elementTypeName must not be null");
setElementTypeName(elementTypeName);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,6 +35,8 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad
private Object source; private Object source;
private String elementTypeName;
private boolean mergeEnabled; private boolean mergeEnabled;
@ -58,6 +60,20 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad
return this.source; return this.source;
} }
/**
* Set the default element type name (class name) to be used for this list.
*/
public void setElementTypeName(String elementTypeName) {
this.elementTypeName = elementTypeName;
}
/**
* Return the default element type name (class name) to be used for this list.
*/
public String getElementTypeName() {
return this.elementTypeName;
}
/** /**
* Set whether merging should be enabled for this collection, * Set whether merging should be enabled for this collection,
* in case of a 'parent' collection value being present. * in case of a 'parent' collection value being present.
@ -70,7 +86,8 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad
return this.mergeEnabled; return this.mergeEnabled;
} }
public Object merge(Object parent) { @SuppressWarnings("unchecked")
public List<E> merge(Object parent) {
if (!this.mergeEnabled) { if (!this.mergeEnabled) {
throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'"); throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'");
} }
@ -80,7 +97,7 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad
if (!(parent instanceof List)) { if (!(parent instanceof List)) {
throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]"); throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]");
} }
List merged = new ManagedList(); List<E> merged = new ManagedList<E>();
merged.addAll((List) parent); merged.addAll((List) parent);
merged.addAll(this); merged.addAll(this);
return merged; return merged;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,6 +34,10 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable,
private Object source; private Object source;
private String keyTypeName;
private String valueTypeName;
private boolean mergeEnabled; private boolean mergeEnabled;
@ -57,6 +61,34 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable,
return this.source; return this.source;
} }
/**
* Set the default key type name (class name) to be used for this map.
*/
public void setKeyTypeName(String keyTypeName) {
this.keyTypeName = keyTypeName;
}
/**
* Return the default key type name (class name) to be used for this map.
*/
public String getKeyTypeName() {
return this.keyTypeName;
}
/**
* Set the default value type name (class name) to be used for this map.
*/
public void setValueTypeName(String valueTypeName) {
this.valueTypeName = valueTypeName;
}
/**
* Return the default value type name (class name) to be used for this map.
*/
public String getValueTypeName() {
return this.valueTypeName;
}
/** /**
* Set whether merging should be enabled for this collection, * Set whether merging should be enabled for this collection,
* in case of a 'parent' collection value being present. * in case of a 'parent' collection value being present.
@ -69,6 +101,7 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable,
return this.mergeEnabled; return this.mergeEnabled;
} }
@SuppressWarnings("unchecked")
public Object merge(Object parent) { public Object merge(Object parent) {
if (!this.mergeEnabled) { if (!this.mergeEnabled) {
throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'"); throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'");
@ -79,7 +112,7 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable,
if (!(parent instanceof Map)) { if (!(parent instanceof Map)) {
throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]"); throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]");
} }
Map merged = new ManagedMap(); Map<K, V> merged = new ManagedMap<K, V>();
merged.putAll((Map) parent); merged.putAll((Map) parent);
merged.putAll(this); merged.putAll(this);
return merged; return merged;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,6 +34,8 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe
private Object source; private Object source;
private String elementTypeName;
private boolean mergeEnabled; private boolean mergeEnabled;
@ -57,6 +59,20 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe
return this.source; return this.source;
} }
/**
* Set the default element type name (class name) to be used for this set.
*/
public void setElementTypeName(String elementTypeName) {
this.elementTypeName = elementTypeName;
}
/**
* Return the default element type name (class name) to be used for this set.
*/
public String getElementTypeName() {
return this.elementTypeName;
}
/** /**
* Set whether merging should be enabled for this collection, * Set whether merging should be enabled for this collection,
* in case of a 'parent' collection value being present. * in case of a 'parent' collection value being present.
@ -69,7 +85,8 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe
return this.mergeEnabled; return this.mergeEnabled;
} }
public Object merge(Object parent) { @SuppressWarnings("unchecked")
public Set<E> merge(Object parent) {
if (!this.mergeEnabled) { if (!this.mergeEnabled) {
throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'"); throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'");
} }
@ -79,7 +96,7 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe
if (!(parent instanceof Set)) { if (!(parent instanceof Set)) {
throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]"); throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]");
} }
Set merged = new ManagedSet(); Set<E> merged = new ManagedSet<E>();
merged.addAll((Set) parent); merged.addAll((Set) parent);
merged.addAll(this); merged.addAll(this);
return merged; return merged;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package org.springframework.beans.factory.xml;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -26,6 +27,11 @@ import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.springframework.beans.BeanMetadataAttribute; import org.springframework.beans.BeanMetadataAttribute;
import org.springframework.beans.BeanMetadataAttributeAccessor; import org.springframework.beans.BeanMetadataAttributeAccessor;
import org.springframework.beans.PropertyValue; import org.springframework.beans.PropertyValue;
@ -45,6 +51,7 @@ import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.BeanDefinitionDefaults; import org.springframework.beans.factory.support.BeanDefinitionDefaults;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.LookupOverride; import org.springframework.beans.factory.support.LookupOverride;
import org.springframework.beans.factory.support.ManagedArray;
import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.ManagedProperties; import org.springframework.beans.factory.support.ManagedProperties;
@ -58,10 +65,6 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.PatternMatchUtils; import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils; import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/** /**
* Stateful delegate class used to parse XML bean definitions. * Stateful delegate class used to parse XML bean definitions.
@ -185,6 +188,8 @@ public class BeanDefinitionParserDelegate {
public static final String NULL_ELEMENT = "null"; public static final String NULL_ELEMENT = "null";
public static final String ARRAY_ELEMENT = "array";
public static final String LIST_ELEMENT = "list"; public static final String LIST_ELEMENT = "list";
public static final String SET_ELEMENT = "set"; public static final String SET_ELEMENT = "set";
@ -424,7 +429,7 @@ public class BeanDefinitionParserDelegate {
/** /**
* Validate that the specified bean name and aliases have not been used already. * Validate that the specified bean name and aliases have not been used already.
*/ */
protected void checkNameUniqueness(String beanName, List aliases, Element beanElement) { protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {
String foundName = null; String foundName = null;
if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) { if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {
@ -651,18 +656,18 @@ public class BeanDefinitionParserDelegate {
if (DEFAULT_VALUE.equals(att)) { if (DEFAULT_VALUE.equals(att)) {
att = this.defaults.getDependencyCheck(); att = this.defaults.getDependencyCheck();
} }
int dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE;
if (DEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE.equals(att)) { if (DEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE.equals(att)) {
dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_ALL; return AbstractBeanDefinition.DEPENDENCY_CHECK_ALL;
}
else if (DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE.equals(att)) {
dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE;
} }
else if (DEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE.equals(att)) { else if (DEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE.equals(att)) {
dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS; return AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS;
}
else if (DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE.equals(att)) {
return AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE;
}
else {
return AbstractBeanDefinition.DEPENDENCY_CHECK_NONE;
} }
// Else leave default value.
return dependencyCheckCode;
} }
/** /**
@ -928,10 +933,10 @@ public class BeanDefinitionParserDelegate {
* Parse a value, ref or collection sub-element of a property or * Parse a value, ref or collection sub-element of a property or
* constructor-arg element. * constructor-arg element.
* @param ele subelement of property element; we don't know which yet * @param ele subelement of property element; we don't know which yet
* @param defaultTypeClassName the default type (class name) for any * @param defaultValueType the default type (class name) for any
* <code>&lt;value&gt;</code> tag that might be created * <code>&lt;value&gt;</code> tag that might be created
*/ */
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultTypeClassName) { public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
if (!isDefaultNamespace(ele.getNamespaceURI())) { if (!isDefaultNamespace(ele.getNamespaceURI())) {
return parseNestedCustomElement(ele, bd); return parseNestedCustomElement(ele, bd);
} }
@ -971,7 +976,7 @@ public class BeanDefinitionParserDelegate {
return parseIdRefElement(ele); return parseIdRefElement(ele);
} }
else if (DomUtils.nodeNameEquals(ele, VALUE_ELEMENT)) { else if (DomUtils.nodeNameEquals(ele, VALUE_ELEMENT)) {
return parseValueElement(ele, defaultTypeClassName); return parseValueElement(ele, defaultValueType);
} }
else if (DomUtils.nodeNameEquals(ele, NULL_ELEMENT)) { else if (DomUtils.nodeNameEquals(ele, NULL_ELEMENT)) {
// It's a distinguished null value. Let's wrap it in a TypedStringValue // It's a distinguished null value. Let's wrap it in a TypedStringValue
@ -980,6 +985,9 @@ public class BeanDefinitionParserDelegate {
nullHolder.setSource(extractSource(ele)); nullHolder.setSource(extractSource(ele));
return nullHolder; return nullHolder;
} }
else if (DomUtils.nodeNameEquals(ele, ARRAY_ELEMENT)) {
return parseArrayElement(ele, bd);
}
else if (DomUtils.nodeNameEquals(ele, LIST_ELEMENT)) { else if (DomUtils.nodeNameEquals(ele, LIST_ELEMENT)) {
return parseListElement(ele, bd); return parseListElement(ele, bd);
} }
@ -1024,18 +1032,22 @@ public class BeanDefinitionParserDelegate {
/** /**
* Return a typed String value Object for the given value element. * Return a typed String value Object for the given value element.
*/ */
public Object parseValueElement(Element ele, String defaultTypeClassName) { public Object parseValueElement(Element ele, String defaultTypeName) {
// It's a literal value. // It's a literal value.
String value = DomUtils.getTextValue(ele); String value = DomUtils.getTextValue(ele);
String typeClassName = ele.getAttribute(TYPE_ATTRIBUTE); String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);
if (!StringUtils.hasText(typeClassName)) { String typeName = specifiedTypeName;
typeClassName = defaultTypeClassName; if (!StringUtils.hasText(typeName)) {
typeName = defaultTypeName;
} }
try { try {
return buildTypedStringValue(value, typeClassName, ele); TypedStringValue typedValue = buildTypedStringValue(value, typeName);
typedValue.setSource(extractSource(ele));
typedValue.setSpecifiedTypeName(specifiedTypeName);
return typedValue;
} }
catch (ClassNotFoundException ex) { catch (ClassNotFoundException ex) {
error("Type class [" + typeClassName + "] not found for <value> element", ele, ex); error("Type class [" + typeName + "] not found for <value> element", ele, ex);
return value; return value;
} }
} }
@ -1044,11 +1056,11 @@ public class BeanDefinitionParserDelegate {
* Build a typed String value Object for the given raw value. * Build a typed String value Object for the given raw value.
* @see org.springframework.beans.factory.config.TypedStringValue * @see org.springframework.beans.factory.config.TypedStringValue
*/ */
protected Object buildTypedStringValue(String value, String targetTypeName, Element ele) protected TypedStringValue buildTypedStringValue(String value, String targetTypeName)
throws ClassNotFoundException { throws ClassNotFoundException {
ClassLoader classLoader = this.readerContext.getBeanClassLoader(); ClassLoader classLoader = this.readerContext.getBeanClassLoader();
TypedStringValue typedValue = null; TypedStringValue typedValue;
if (!StringUtils.hasText(targetTypeName)) { if (!StringUtils.hasText(targetTypeName)) {
typedValue = new TypedStringValue(value); typedValue = new TypedStringValue(value);
} }
@ -1059,57 +1071,75 @@ public class BeanDefinitionParserDelegate {
else { else {
typedValue = new TypedStringValue(value, targetTypeName); typedValue = new TypedStringValue(value, targetTypeName);
} }
typedValue.setSource(extractSource(ele));
return typedValue; return typedValue;
} }
/**
* Parse an array element.
*/
public Object parseArrayElement(Element arrayEle, BeanDefinition bd) {
String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
NodeList nl = arrayEle.getChildNodes();
ManagedArray target = new ManagedArray(elementType, nl.getLength());
target.setSource(extractSource(arrayEle));
target.setElementTypeName(elementType);
target.setMergeEnabled(parseMergeAttribute(arrayEle));
parseCollectionElements(nl, target, bd, elementType);
return target;
}
/** /**
* Parse a list element. * Parse a list element.
*/ */
public List<?> parseListElement(Element collectionEle, BeanDefinition bd) { public List parseListElement(Element collectionEle, BeanDefinition bd) {
String defaultTypeClassName = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE); String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
NodeList nl = collectionEle.getChildNodes(); NodeList nl = collectionEle.getChildNodes();
ManagedList list = new ManagedList(nl.getLength()); ManagedList<Object> target = new ManagedList<Object>(nl.getLength());
list.setSource(extractSource(collectionEle)); target.setSource(extractSource(collectionEle));
list.setMergeEnabled(parseMergeAttribute(collectionEle)); target.setElementTypeName(defaultElementType);
for (int i = 0; i < nl.getLength(); i++) { target.setMergeEnabled(parseMergeAttribute(collectionEle));
Node node = nl.item(i); parseCollectionElements(nl, target, bd, defaultElementType);
if (node instanceof Element && !DomUtils.nodeNameEquals(node, DESCRIPTION_ELEMENT)) { return target;
list.add(parsePropertySubElement((Element) node, bd, defaultTypeClassName));
}
}
return list;
} }
/** /**
* Parse a set element. * Parse a set element.
*/ */
public Set parseSetElement(Element collectionEle, BeanDefinition bd) { public Set parseSetElement(Element collectionEle, BeanDefinition bd) {
String defaultTypeClassName = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE); String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
NodeList nl = collectionEle.getChildNodes(); NodeList nl = collectionEle.getChildNodes();
ManagedSet set = new ManagedSet(nl.getLength()); ManagedSet<Object> target = new ManagedSet<Object>(nl.getLength());
set.setSource(extractSource(collectionEle)); target.setSource(extractSource(collectionEle));
set.setMergeEnabled(parseMergeAttribute(collectionEle)); target.setElementTypeName(defaultElementType);
for (int i = 0; i < nl.getLength(); i++) { target.setMergeEnabled(parseMergeAttribute(collectionEle));
Node node = nl.item(i); parseCollectionElements(nl, target, bd, defaultElementType);
return target;
}
protected void parseCollectionElements(
NodeList elementNodes, Collection<Object> target, BeanDefinition bd, String defaultElementType) {
for (int i = 0; i < elementNodes.getLength(); i++) {
Node node = elementNodes.item(i);
if (node instanceof Element && !DomUtils.nodeNameEquals(node, DESCRIPTION_ELEMENT)) { if (node instanceof Element && !DomUtils.nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
set.add(parsePropertySubElement((Element) node, bd, defaultTypeClassName)); target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
} }
} }
return set;
} }
/** /**
* Parse a map element. * Parse a map element.
*/ */
public Map parseMapElement(Element mapEle, BeanDefinition bd) { public Map parseMapElement(Element mapEle, BeanDefinition bd) {
String defaultKeyTypeClassName = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE); String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE);
String defaultValueTypeClassName = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE); String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT); List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT);
ManagedMap map = new ManagedMap(entryEles.size()); ManagedMap<Object, Object> map = new ManagedMap<Object, Object>(entryEles.size());
map.setMergeEnabled(parseMergeAttribute(mapEle));
map.setSource(extractSource(mapEle)); map.setSource(extractSource(mapEle));
map.setKeyTypeName(defaultKeyType);
map.setValueTypeName(defaultValueType);
map.setMergeEnabled(parseMergeAttribute(mapEle));
for (Element entryEle : entryEles) { for (Element entryEle : entryEles) {
// Should only have one value child element: ref, value, list, etc. // Should only have one value child element: ref, value, list, etc.
@ -1151,8 +1181,7 @@ public class BeanDefinitionParserDelegate {
"a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element", entryEle); "a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element", entryEle);
} }
if (hasKeyAttribute) { if (hasKeyAttribute) {
key = buildTypedStringValueForMap( key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle);
entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyTypeClassName, entryEle);
} }
else if (hasKeyRefAttribute) { else if (hasKeyRefAttribute) {
String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE); String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE);
@ -1164,7 +1193,7 @@ public class BeanDefinitionParserDelegate {
key = ref; key = ref;
} }
else if (keyEle != null) { else if (keyEle != null) {
key = parseKeyElement(keyEle, bd, defaultKeyTypeClassName); key = parseKeyElement(keyEle, bd, defaultKeyType);
} }
else { else {
error("<entry> element must specify a key", entryEle); error("<entry> element must specify a key", entryEle);
@ -1180,8 +1209,7 @@ public class BeanDefinitionParserDelegate {
"'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle); "'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle);
} }
if (hasValueAttribute) { if (hasValueAttribute) {
value = buildTypedStringValueForMap( value = buildTypedStringValueForMap(entryEle.getAttribute(VALUE_ATTRIBUTE), defaultValueType, entryEle);
entryEle.getAttribute(VALUE_ATTRIBUTE), defaultValueTypeClassName, entryEle);
} }
else if (hasValueRefAttribute) { else if (hasValueRefAttribute) {
String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE); String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE);
@ -1193,7 +1221,7 @@ public class BeanDefinitionParserDelegate {
value = ref; value = ref;
} }
else if (valueEle != null) { else if (valueEle != null) {
value = parsePropertySubElement(valueEle, bd, defaultValueTypeClassName); value = parsePropertySubElement(valueEle, bd, defaultValueType);
} }
else { else {
error("<entry> element must specify a value", entryEle); error("<entry> element must specify a value", entryEle);
@ -1210,12 +1238,14 @@ public class BeanDefinitionParserDelegate {
* Build a typed String value Object for the given raw value. * Build a typed String value Object for the given raw value.
* @see org.springframework.beans.factory.config.TypedStringValue * @see org.springframework.beans.factory.config.TypedStringValue
*/ */
protected final Object buildTypedStringValueForMap(String value, String defaultTypeClassName, Element entryEle) { protected final Object buildTypedStringValueForMap(String value, String defaultTypeName, Element entryEle) {
try { try {
return buildTypedStringValue(value, defaultTypeClassName, entryEle); TypedStringValue typedValue = buildTypedStringValue(value, defaultTypeName);
typedValue.setSource(extractSource(entryEle));
return typedValue;
} }
catch (ClassNotFoundException ex) { catch (ClassNotFoundException ex) {
error("Type class [" + defaultTypeClassName + "] not found for Map key/value type", entryEle, ex); error("Type class [" + defaultTypeName + "] not found for Map key/value type", entryEle, ex);
return value; return value;
} }
} }
@ -1223,7 +1253,7 @@ public class BeanDefinitionParserDelegate {
/** /**
* Parse a key sub-element of a map element. * Parse a key sub-element of a map element.
*/ */
public Object parseKeyElement(Element keyEle, BeanDefinition bd, String defaultKeyTypeClassName) { protected Object parseKeyElement(Element keyEle, BeanDefinition bd, String defaultKeyTypeName) {
NodeList nl = keyEle.getChildNodes(); NodeList nl = keyEle.getChildNodes();
Element subElement = null; Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) { for (int i = 0; i < nl.getLength(); i++) {
@ -1238,7 +1268,7 @@ public class BeanDefinitionParserDelegate {
} }
} }
} }
return parsePropertySubElement(subElement, bd, defaultKeyTypeClassName); return parsePropertySubElement(subElement, bd, defaultKeyTypeName);
} }
/** /**

View File

@ -1,6 +1,7 @@
http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd

View File

@ -78,7 +78,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'lazy-init' value; see the documentation for the The default 'lazy-init' value; see the documentation for the
'lazy-init' attribute of the '<bean>/' element. 'lazy-init' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
@ -94,7 +94,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'autowire' value; see the documentation for the The default 'autowire' value; see the documentation for the
'autowire' attribute of the '<bean>/' element. 'autowire' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:simpleType> <xsd:simpleType>
@ -111,7 +111,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'dependency-check' value; see the documentation for the The default 'dependency-check' value; see the documentation for the
'dependency-check' attribute of the '<bean>/' element. 'dependency-check' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:simpleType> <xsd:simpleType>
@ -127,7 +127,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'init-method' value; see the documentation for the The default 'init-method' value; see the documentation for the
'init-method' attribute of the '<bean>/' element. 'init-method' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
@ -135,7 +135,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'destroy-method' value; see the documentation for the The default 'destroy-method' value; see the documentation for the
'destroy-method' attribute of the '<bean>/' element. 'destroy-method' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
@ -323,7 +323,7 @@
more explicit. more explicit.
2. "byName" 2. "byName"
Autowiring by property name. If a bean of class Cat exposes a dog Autowiring by property name. If a bean of class Cat exposes a "dog"
property, Spring will try to set this to the value of the bean "dog" property, Spring will try to set this to the value of the bean "dog"
in the current container. If there is no matching bean by name, nothing in the current container. If there is no matching bean by name, nothing
special happens; use dependency-check="objects" to raise an error in special happens; use dependency-check="objects" to raise an error in

View File

@ -78,7 +78,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'lazy-init' value; see the documentation for the The default 'lazy-init' value; see the documentation for the
'lazy-init' attribute of the '<bean>/' element. 'lazy-init' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
@ -94,7 +94,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'autowire' value; see the documentation for the The default 'autowire' value; see the documentation for the
'autowire' attribute of the '<bean>/' element. 'autowire' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:simpleType> <xsd:simpleType>
@ -111,7 +111,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'dependency-check' value; see the documentation for the The default 'dependency-check' value; see the documentation for the
'dependency-check' attribute of the '<bean>/' element. 'dependency-check' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:simpleType> <xsd:simpleType>
@ -138,7 +138,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'init-method' value; see the documentation for the The default 'init-method' value; see the documentation for the
'init-method' attribute of the '<bean>/' element. 'init-method' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
@ -146,7 +146,7 @@
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The default 'destroy-method' value; see the documentation for the The default 'destroy-method' value; see the documentation for the
'destroy-method' attribute of the '<bean>/' element. 'destroy-method' attribute of the '<bean>' element.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
@ -336,7 +336,7 @@
more explicit. more explicit.
2. "byName" 2. "byName"
Autowiring by property name. If a bean of class Cat exposes a dog Autowiring by property name. If a bean of class Cat exposes a "dog"
property, Spring will try to set this to the value of the bean "dog" property, Spring will try to set this to the value of the bean "dog"
in the current container. If there is no matching bean by name, nothing in the current container. If there is no matching bean by name, nothing
special happens; use dependency-check="objects" to raise an error in special happens; use dependency-check="objects" to raise an error in

View File

@ -1,60 +1,90 @@
/*
* Copyright 2002-2009 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
*
* http://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.xml; package org.springframework.beans.factory.xml;
import junit.framework.TestCase; import java.util.List;
import org.springframework.core.io.ClassPathResource; import java.util.Map;
import static org.junit.Assert.*;
import org.junit.Test;
import test.beans.TestBean; import test.beans.TestBean;
import java.util.List; import org.springframework.core.io.ClassPathResource;
import java.util.Set;
import java.util.Iterator;
import java.util.Map;
/** /**
* @author Rob Harrop * @author Rob Harrop
* @author Juergen Hoeller
*/ */
public class CollectionsWithDefaultTypesTests extends TestCase { public class CollectionsWithDefaultTypesTests {
private XmlBeanFactory beanFactory; private final XmlBeanFactory beanFactory;
protected void setUp() throws Exception { public CollectionsWithDefaultTypesTests() {
this.beanFactory = new XmlBeanFactory(new ClassPathResource("collectionsWithDefaultTypes.xml", getClass())); this.beanFactory = new XmlBeanFactory(new ClassPathResource("collectionsWithDefaultTypes.xml", getClass()));
} }
@Test
public void testListHasDefaultType() throws Exception { public void testListHasDefaultType() throws Exception {
TestBean bean = (TestBean) this.beanFactory.getBean("testBean"); TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
List list = bean.getSomeList(); for (Object o : bean.getSomeList()) {
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
assertEquals("Value type is incorrect", Integer.class, o.getClass()); assertEquals("Value type is incorrect", Integer.class, o.getClass());
} }
} }
@Test
public void testSetHasDefaultType() throws Exception { public void testSetHasDefaultType() throws Exception {
TestBean bean = (TestBean) this.beanFactory.getBean("testBean"); TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
Set set = bean.getSomeSet(); for (Object o : bean.getSomeSet()) {
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object o = iterator.next();
assertEquals("Value type is incorrect", Integer.class, o.getClass()); assertEquals("Value type is incorrect", Integer.class, o.getClass());
} }
} }
@Test
public void testMapHasDefaultKeyAndValueType() throws Exception { public void testMapHasDefaultKeyAndValueType() throws Exception {
TestBean bean = (TestBean) this.beanFactory.getBean("testBean"); TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
assertMap(bean.getSomeMap()); assertMap(bean.getSomeMap());
} }
@Test
public void testMapWithNestedElementsHasDefaultKeyAndValueType() throws Exception { public void testMapWithNestedElementsHasDefaultKeyAndValueType() throws Exception {
TestBean bean = (TestBean) this.beanFactory.getBean("testBean2"); TestBean bean = (TestBean) this.beanFactory.getBean("testBean2");
assertMap(bean.getSomeMap()); assertMap(bean.getSomeMap());
} }
private void assertMap(Map map) { private void assertMap(Map<?,?> map) {
for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) { for (Map.Entry entry : map.entrySet()) {
Map.Entry entry = (Map.Entry) iterator.next();
assertEquals("Key type is incorrect", Integer.class, entry.getKey().getClass()); assertEquals("Key type is incorrect", Integer.class, entry.getKey().getClass());
assertEquals("Value type is incorrect", Boolean.class, entry.getValue().getClass()); assertEquals("Value type is incorrect", Boolean.class, entry.getValue().getClass());
} }
} }
@Test
public void testBuildCollectionFromMixtureOfReferencesAndValues() throws Exception {
MixedCollectionBean jumble = (MixedCollectionBean) this.beanFactory.getBean("jumble");
assertTrue("Expected 3 elements, not " + jumble.getJumble().size(),
jumble.getJumble().size() == 3);
List l = (List) jumble.getJumble();
assertTrue(l.get(0).equals("literal"));
Integer[] array1 = (Integer[]) l.get(1);
assertTrue(array1[0].equals(new Integer(2)));
assertTrue(array1[1].equals(new Integer(4)));
int[] array2 = (int[]) l.get(2);
assertTrue(array2[0] == 3);
assertTrue(array2[1] == 5);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2007 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,8 +16,6 @@
package org.springframework.beans.factory.xml; package org.springframework.beans.factory.xml;
import static org.junit.Assert.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -30,7 +28,10 @@ import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet; import java.util.TreeSet;
import static org.junit.Assert.*;
import org.junit.Test; import org.junit.Test;
import test.beans.TestBean;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.ListFactoryBean; import org.springframework.beans.factory.config.ListFactoryBean;
@ -38,8 +39,6 @@ import org.springframework.beans.factory.config.MapFactoryBean;
import org.springframework.beans.factory.config.SetFactoryBean; import org.springframework.beans.factory.config.SetFactoryBean;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import test.beans.TestBean;
/** /**
* Tests for collections in XML bean definitions. * Tests for collections in XML bean definitions.
* *
@ -49,6 +48,12 @@ import test.beans.TestBean;
*/ */
public class XmlBeanCollectionTests { public class XmlBeanCollectionTests {
private final XmlBeanFactory beanFactory;
public XmlBeanCollectionTests() {
this.beanFactory = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
}
@Test @Test
public void testCollectionFactoryDefaults() throws Exception { public void testCollectionFactoryDefaults() throws Exception {
ListFactoryBean listFactory = new ListFactoryBean(); ListFactoryBean listFactory = new ListFactoryBean();
@ -69,40 +74,35 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testRefSubelement() throws Exception { public void testRefSubelement() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); //assertTrue("5 beans in reftypes, not " + this.beanFactory.getBeanDefinitionCount(), this.beanFactory.getBeanDefinitionCount() == 5);
//assertTrue("5 beans in reftypes, not " + xbf.getBeanDefinitionCount(), xbf.getBeanDefinitionCount() == 5); TestBean jen = (TestBean) this.beanFactory.getBean("jenny");
TestBean jen = (TestBean) xbf.getBean("jenny"); TestBean dave = (TestBean) this.beanFactory.getBean("david");
TestBean dave = (TestBean) xbf.getBean("david");
assertTrue(jen.getSpouse() == dave); assertTrue(jen.getSpouse() == dave);
} }
@Test @Test
public void testPropertyWithLiteralValueSubelement() throws Exception { public void testPropertyWithLiteralValueSubelement() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); TestBean verbose = (TestBean) this.beanFactory.getBean("verbose");
TestBean verbose = (TestBean) xbf.getBean("verbose");
assertTrue(verbose.getName().equals("verbose")); assertTrue(verbose.getName().equals("verbose"));
} }
@Test @Test
public void testPropertyWithIdRefLocalAttrSubelement() throws Exception { public void testPropertyWithIdRefLocalAttrSubelement() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); TestBean verbose = (TestBean) this.beanFactory.getBean("verbose2");
TestBean verbose = (TestBean) xbf.getBean("verbose2");
assertTrue(verbose.getName().equals("verbose")); assertTrue(verbose.getName().equals("verbose"));
} }
@Test @Test
public void testPropertyWithIdRefBeanAttrSubelement() throws Exception { public void testPropertyWithIdRefBeanAttrSubelement() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); TestBean verbose = (TestBean) this.beanFactory.getBean("verbose3");
TestBean verbose = (TestBean) xbf.getBean("verbose3");
assertTrue(verbose.getName().equals("verbose")); assertTrue(verbose.getName().equals("verbose"));
} }
@Test @Test
public void testRefSubelementsBuildCollection() throws Exception { public void testRefSubelementsBuildCollection() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); TestBean jen = (TestBean) this.beanFactory.getBean("jenny");
TestBean jen = (TestBean) xbf.getBean("jenny"); TestBean dave = (TestBean) this.beanFactory.getBean("david");
TestBean dave = (TestBean) xbf.getBean("david"); TestBean rod = (TestBean) this.beanFactory.getBean("rod");
TestBean rod = (TestBean) xbf.getBean("rod");
// Must be a list to support ordering // Must be a list to support ordering
// Our bean doesn't modify the collection: // Our bean doesn't modify the collection:
@ -117,11 +117,9 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testRefSubelementsBuildCollectionWithPrototypes() throws Exception { public void testRefSubelementsBuildCollectionWithPrototypes() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); TestBean jen = (TestBean) this.beanFactory.getBean("pJenny");
TestBean dave = (TestBean) this.beanFactory.getBean("pDavid");
TestBean jen = (TestBean) xbf.getBean("pJenny"); TestBean rod = (TestBean) this.beanFactory.getBean("pRod");
TestBean dave = (TestBean) xbf.getBean("pDavid");
TestBean rod = (TestBean) xbf.getBean("pRod");
Object[] friends = rod.getFriends().toArray(); Object[] friends = rod.getFriends().toArray();
assertTrue(friends.length == 2); assertTrue(friends.length == 2);
assertTrue("First friend must be jen, not " + friends[0], assertTrue("First friend must be jen, not " + friends[0],
@ -130,7 +128,7 @@ public class XmlBeanCollectionTests {
assertTrue(friends[1].toString().equals(dave.toString())); assertTrue(friends[1].toString().equals(dave.toString()));
assertTrue("Dave not same instance", friends[1] != dave); assertTrue("Dave not same instance", friends[1] != dave);
TestBean rod2 = (TestBean) xbf.getBean("pRod"); TestBean rod2 = (TestBean) this.beanFactory.getBean("pRod");
Object[] friends2 = rod2.getFriends().toArray(); Object[] friends2 = rod2.getFriends().toArray();
assertTrue(friends2.length == 2); assertTrue(friends2.length == 2);
assertTrue("First friend must be jen, not " + friends2[0], assertTrue("First friend must be jen, not " + friends2[0],
@ -142,50 +140,48 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testRefSubelementsBuildCollectionFromSingleElement() throws Exception { public void testRefSubelementsBuildCollectionFromSingleElement() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); TestBean loner = (TestBean) this.beanFactory.getBean("loner");
TestBean loner = (TestBean) xbf.getBean("loner"); TestBean dave = (TestBean) this.beanFactory.getBean("david");
TestBean dave = (TestBean) xbf.getBean("david");
assertTrue(loner.getFriends().size() == 1); assertTrue(loner.getFriends().size() == 1);
assertTrue(loner.getFriends().contains(dave)); assertTrue(loner.getFriends().contains(dave));
} }
@Test @Test
public void testBuildCollectionFromMixtureOfReferencesAndValues() throws Exception { public void testBuildCollectionFromMixtureOfReferencesAndValues() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); MixedCollectionBean jumble = (MixedCollectionBean) this.beanFactory.getBean("jumble");
MixedCollectionBean jumble = (MixedCollectionBean) xbf.getBean("jumble"); assertTrue("Expected 5 elements, not " + jumble.getJumble().size(),
assertTrue("Expected 4 elements, not " + jumble.getJumble().size(), jumble.getJumble().size() == 5);
jumble.getJumble().size() == 4);
List l = (List) jumble.getJumble(); List l = (List) jumble.getJumble();
assertTrue(l.get(0).equals(xbf.getBean("david"))); assertTrue(l.get(0).equals(this.beanFactory.getBean("david")));
assertTrue(l.get(1).equals("literal")); assertTrue(l.get(1).equals("literal"));
assertTrue(l.get(2).equals(xbf.getBean("jenny"))); assertTrue(l.get(2).equals(this.beanFactory.getBean("jenny")));
assertTrue(l.get(3).equals("rod")); assertTrue(l.get(3).equals("rod"));
Object[] array = (Object[]) l.get(4);
assertTrue(array[0].equals(this.beanFactory.getBean("david")));
assertTrue(array[1].equals("literal2"));
} }
@Test @Test
public void testInvalidBeanNameReference() throws Exception { public void testInvalidBeanNameReference() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
try { try {
xbf.getBean("jumble2"); this.beanFactory.getBean("jumble2");
fail("Should have thrown BeanCreationException"); fail("Should have thrown BeanCreationException");
} }
catch (BeanCreationException ex) { catch (BeanCreationException ex) {
assertTrue(ex.getCause() instanceof BeanDefinitionStoreException); assertTrue(ex.getCause() instanceof BeanDefinitionStoreException);
assertTrue(ex.getCause().getMessage().indexOf("rod2") != -1); assertTrue(ex.getCause().getMessage().contains("rod2"));
} }
} }
@Test @Test
public void testEmptyMap() throws Exception { public void testEmptyMap() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("emptyMap");
HasMap hasMap = (HasMap) xbf.getBean("emptyMap");
assertTrue(hasMap.getMap().size() == 0); assertTrue(hasMap.getMap().size() == 0);
} }
@Test @Test
public void testMapWithLiteralsOnly() throws Exception { public void testMapWithLiteralsOnly() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("literalMap");
HasMap hasMap = (HasMap) xbf.getBean("literalMap");
assertTrue(hasMap.getMap().size() == 3); assertTrue(hasMap.getMap().size() == 3);
assertTrue(hasMap.getMap().get("foo").equals("bar")); assertTrue(hasMap.getMap().get("foo").equals("bar"));
assertTrue(hasMap.getMap().get("fi").equals("fum")); assertTrue(hasMap.getMap().get("fi").equals("fum"));
@ -194,27 +190,24 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testMapWithLiteralsAndReferences() throws Exception { public void testMapWithLiteralsAndReferences() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("mixedMap");
HasMap hasMap = (HasMap) xbf.getBean("mixedMap");
assertTrue(hasMap.getMap().size() == 3); assertTrue(hasMap.getMap().size() == 3);
assertTrue(hasMap.getMap().get("foo").equals(new Integer(10))); assertTrue(hasMap.getMap().get("foo").equals(new Integer(10)));
TestBean jenny = (TestBean) xbf.getBean("jenny"); TestBean jenny = (TestBean) this.beanFactory.getBean("jenny");
assertTrue(hasMap.getMap().get("jenny") == jenny); assertTrue(hasMap.getMap().get("jenny") == jenny);
assertTrue(hasMap.getMap().get(new Integer(5)).equals("david")); assertTrue(hasMap.getMap().get(new Integer(5)).equals("david"));
} }
@Test @Test
public void testMapWithLiteralsAndPrototypeReferences() throws Exception { public void testMapWithLiteralsAndPrototypeReferences() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); TestBean jenny = (TestBean) this.beanFactory.getBean("pJenny");
HasMap hasMap = (HasMap) this.beanFactory.getBean("pMixedMap");
TestBean jenny = (TestBean) xbf.getBean("pJenny");
HasMap hasMap = (HasMap) xbf.getBean("pMixedMap");
assertTrue(hasMap.getMap().size() == 2); assertTrue(hasMap.getMap().size() == 2);
assertTrue(hasMap.getMap().get("foo").equals("bar")); assertTrue(hasMap.getMap().get("foo").equals("bar"));
assertTrue(hasMap.getMap().get("jenny").toString().equals(jenny.toString())); assertTrue(hasMap.getMap().get("jenny").toString().equals(jenny.toString()));
assertTrue("Not same instance", hasMap.getMap().get("jenny") != jenny); assertTrue("Not same instance", hasMap.getMap().get("jenny") != jenny);
HasMap hasMap2 = (HasMap) xbf.getBean("pMixedMap"); HasMap hasMap2 = (HasMap) this.beanFactory.getBean("pMixedMap");
assertTrue(hasMap2.getMap().size() == 2); assertTrue(hasMap2.getMap().size() == 2);
assertTrue(hasMap2.getMap().get("foo").equals("bar")); assertTrue(hasMap2.getMap().get("foo").equals("bar"));
assertTrue(hasMap2.getMap().get("jenny").toString().equals(jenny.toString())); assertTrue(hasMap2.getMap().get("jenny").toString().equals(jenny.toString()));
@ -223,11 +216,10 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testMapWithLiteralsReferencesAndList() throws Exception { public void testMapWithLiteralsReferencesAndList() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("mixedMapWithList");
HasMap hasMap = (HasMap) xbf.getBean("mixedMapWithList");
assertTrue(hasMap.getMap().size() == 4); assertTrue(hasMap.getMap().size() == 4);
assertTrue(hasMap.getMap().get(null).equals("bar")); assertTrue(hasMap.getMap().get(null).equals("bar"));
TestBean jenny = (TestBean) xbf.getBean("jenny"); TestBean jenny = (TestBean) this.beanFactory.getBean("jenny");
assertTrue(hasMap.getMap().get("jenny").equals(jenny)); assertTrue(hasMap.getMap().get("jenny").equals(jenny));
// Check list // Check list
@ -263,18 +255,16 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testEmptySet() throws Exception { public void testEmptySet() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("emptySet");
HasMap hasMap = (HasMap) xbf.getBean("emptySet");
assertTrue(hasMap.getSet().size() == 0); assertTrue(hasMap.getSet().size() == 0);
} }
@Test @Test
public void testPopulatedSet() throws Exception { public void testPopulatedSet() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("set");
HasMap hasMap = (HasMap) xbf.getBean("set");
assertTrue(hasMap.getSet().size() == 3); assertTrue(hasMap.getSet().size() == 3);
assertTrue(hasMap.getSet().contains("bar")); assertTrue(hasMap.getSet().contains("bar"));
TestBean jenny = (TestBean) xbf.getBean("jenny"); TestBean jenny = (TestBean) this.beanFactory.getBean("jenny");
assertTrue(hasMap.getSet().contains(jenny)); assertTrue(hasMap.getSet().contains(jenny));
assertTrue(hasMap.getSet().contains(null)); assertTrue(hasMap.getSet().contains(null));
Iterator it = hasMap.getSet().iterator(); Iterator it = hasMap.getSet().iterator();
@ -285,16 +275,14 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testEmptyProps() throws Exception { public void testEmptyProps() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("emptyProps");
HasMap hasMap = (HasMap) xbf.getBean("emptyProps");
assertTrue(hasMap.getProps().size() == 0); assertTrue(hasMap.getProps().size() == 0);
assertEquals(hasMap.getProps().getClass(), Properties.class); assertEquals(hasMap.getProps().getClass(), Properties.class);
} }
@Test @Test
public void testPopulatedProps() throws Exception { public void testPopulatedProps() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("props");
HasMap hasMap = (HasMap) xbf.getBean("props");
assertTrue(hasMap.getProps().size() == 2); assertTrue(hasMap.getProps().size() == 2);
assertTrue(hasMap.getProps().get("foo").equals("bar")); assertTrue(hasMap.getProps().get("foo").equals("bar"));
assertTrue(hasMap.getProps().get("2").equals("TWO")); assertTrue(hasMap.getProps().get("2").equals("TWO"));
@ -302,17 +290,15 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testObjectArray() throws Exception { public void testObjectArray() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("objectArray");
HasMap hasMap = (HasMap) xbf.getBean("objectArray");
assertTrue(hasMap.getObjectArray().length == 2); assertTrue(hasMap.getObjectArray().length == 2);
assertTrue(hasMap.getObjectArray()[0].equals("one")); assertTrue(hasMap.getObjectArray()[0].equals("one"));
assertTrue(hasMap.getObjectArray()[1].equals(xbf.getBean("jenny"))); assertTrue(hasMap.getObjectArray()[1].equals(this.beanFactory.getBean("jenny")));
} }
@Test @Test
public void testClassArray() throws Exception { public void testClassArray() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("classArray");
HasMap hasMap = (HasMap) xbf.getBean("classArray");
assertTrue(hasMap.getClassArray().length == 2); assertTrue(hasMap.getClassArray().length == 2);
assertTrue(hasMap.getClassArray()[0].equals(String.class)); assertTrue(hasMap.getClassArray()[0].equals(String.class));
assertTrue(hasMap.getClassArray()[1].equals(Exception.class)); assertTrue(hasMap.getClassArray()[1].equals(Exception.class));
@ -320,8 +306,7 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testIntegerArray() throws Exception { public void testIntegerArray() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("integerArray");
HasMap hasMap = (HasMap) xbf.getBean("integerArray");
assertTrue(hasMap.getIntegerArray().length == 3); assertTrue(hasMap.getIntegerArray().length == 3);
assertTrue(hasMap.getIntegerArray()[0].intValue() == 0); assertTrue(hasMap.getIntegerArray()[0].intValue() == 0);
assertTrue(hasMap.getIntegerArray()[1].intValue() == 1); assertTrue(hasMap.getIntegerArray()[1].intValue() == 1);
@ -330,14 +315,12 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testProps() throws Exception { public void testProps() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); HasMap hasMap = (HasMap) this.beanFactory.getBean("props");
HasMap hasMap = (HasMap) xbf.getBean("props");
assertEquals(2, hasMap.getProps().size()); assertEquals(2, hasMap.getProps().size());
assertEquals("bar", hasMap.getProps().getProperty("foo")); assertEquals("bar", hasMap.getProps().getProperty("foo"));
assertEquals("TWO", hasMap.getProps().getProperty("2")); assertEquals("TWO", hasMap.getProps().getProperty("2"));
HasMap hasMap2 = (HasMap) xbf.getBean("propsViaMap"); HasMap hasMap2 = (HasMap) this.beanFactory.getBean("propsViaMap");
assertEquals(2, hasMap2.getProps().size()); assertEquals(2, hasMap2.getProps().size());
assertEquals("bar", hasMap2.getProps().getProperty("foo")); assertEquals("bar", hasMap2.getProps().getProperty("foo"));
assertEquals("TWO", hasMap2.getProps().getProperty("2")); assertEquals("TWO", hasMap2.getProps().getProperty("2"));
@ -345,8 +328,7 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testListFactory() throws Exception { public void testListFactory() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); List list = (List) this.beanFactory.getBean("listFactory");
List list = (List) xbf.getBean("listFactory");
assertTrue(list instanceof LinkedList); assertTrue(list instanceof LinkedList);
assertTrue(list.size() == 2); assertTrue(list.size() == 2);
assertEquals("bar", list.get(0)); assertEquals("bar", list.get(0));
@ -355,8 +337,7 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testPrototypeListFactory() throws Exception { public void testPrototypeListFactory() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); List list = (List) this.beanFactory.getBean("pListFactory");
List list = (List) xbf.getBean("pListFactory");
assertTrue(list instanceof LinkedList); assertTrue(list instanceof LinkedList);
assertTrue(list.size() == 2); assertTrue(list.size() == 2);
assertEquals("bar", list.get(0)); assertEquals("bar", list.get(0));
@ -365,8 +346,7 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testSetFactory() throws Exception { public void testSetFactory() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); Set set = (Set) this.beanFactory.getBean("setFactory");
Set set = (Set) xbf.getBean("setFactory");
assertTrue(set instanceof TreeSet); assertTrue(set instanceof TreeSet);
assertTrue(set.size() == 2); assertTrue(set.size() == 2);
assertTrue(set.contains("bar")); assertTrue(set.contains("bar"));
@ -375,8 +355,7 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testPrototypeSetFactory() throws Exception { public void testPrototypeSetFactory() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); Set set = (Set) this.beanFactory.getBean("pSetFactory");
Set set = (Set) xbf.getBean("pSetFactory");
assertTrue(set instanceof TreeSet); assertTrue(set instanceof TreeSet);
assertTrue(set.size() == 2); assertTrue(set.size() == 2);
assertTrue(set.contains("bar")); assertTrue(set.contains("bar"));
@ -385,8 +364,7 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testMapFactory() throws Exception { public void testMapFactory() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); Map map = (Map) this.beanFactory.getBean("mapFactory");
Map map = (Map) xbf.getBean("mapFactory");
assertTrue(map instanceof TreeMap); assertTrue(map instanceof TreeMap);
assertTrue(map.size() == 2); assertTrue(map.size() == 2);
assertEquals("bar", map.get("foo")); assertEquals("bar", map.get("foo"));
@ -395,8 +373,7 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testPrototypeMapFactory() throws Exception { public void testPrototypeMapFactory() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); Map map = (Map) this.beanFactory.getBean("pMapFactory");
Map map = (Map) xbf.getBean("pMapFactory");
assertTrue(map instanceof TreeMap); assertTrue(map instanceof TreeMap);
assertTrue(map.size() == 2); assertTrue(map.size() == 2);
assertEquals("bar", map.get("foo")); assertEquals("bar", map.get("foo"));
@ -405,8 +382,7 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testChoiceBetweenSetAndMap() { public void testChoiceBetweenSetAndMap() {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); MapAndSet sam = (MapAndSet) this.beanFactory.getBean("setAndMap");
MapAndSet sam = (MapAndSet) xbf.getBean("setAndMap");
assertTrue("Didn't choose constructor with Map argument", sam.getObject() instanceof Map); assertTrue("Didn't choose constructor with Map argument", sam.getObject() instanceof Map);
Map map = (Map) sam.getObject(); Map map = (Map) sam.getObject();
assertEquals(3, map.size()); assertEquals(3, map.size());
@ -417,8 +393,7 @@ public class XmlBeanCollectionTests {
@Test @Test
public void testEnumSetFactory() throws Exception { public void testEnumSetFactory() throws Exception {
XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass())); Set set = (Set) this.beanFactory.getBean("enumSetFactory");
Set set = (Set) xbf.getBean("enumSetFactory");
assertTrue(set.size() == 2); assertTrue(set.size() == 2);
assertTrue(set.contains("ONE")); assertTrue(set.contains("ONE"));
assertTrue(set.contains("TWO")); assertTrue(set.contains("TWO"));
@ -516,4 +491,3 @@ class HasMap {
} }
} }

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="jenny" class="test.beans.TestBean"> <bean id="jenny" class="test.beans.TestBean">
<property name="name"><value>Jenny</value></property> <property name="name"><value>Jenny</value></property>
@ -81,6 +81,10 @@
<value>literal</value> <value>literal</value>
<ref local="jenny"/> <ref local="jenny"/>
<idref local="rod"/> <idref local="rod"/>
<array>
<ref local="david"/>
<value>literal2</value>
</array>
</list> </list>
</property> </property>
</bean> </bean>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" <beans xmlns="http://www.springframework.org/schema/beans"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<beans>
<bean id="testBean" class="test.beans.TestBean"> <bean id="testBean" class="test.beans.TestBean">
<property name="someList"> <property name="someList">
<list value-type="java.lang.Integer"> <list value-type="java.lang.Integer">
@ -58,4 +58,21 @@
</map> </map>
</property> </property>
</bean> </bean>
<bean id="jumble" class="org.springframework.beans.factory.xml.MixedCollectionBean">
<property name="jumble">
<list value-type="java.lang.String">
<value>literal</value>
<array value-type="java.lang.Integer">
<value>2</value>
<value>4</value>
</array>
<array value-type="int">
<value>3</value>
<value>5</value>
</array>
</list>
</property>
</bean>
</beans> </beans>