use of org.springframework.beans.factory.config.RuntimeBeanReference in project spring-framework by spring-projects.
the class PropertiesBeanDefinitionReader method registerBeanDefinition.
/**
* Get all property values, given a prefix (which will be stripped)
* and add the bean they define to the factory with the given name
* @param beanName name of the bean to define
* @param map Map containing string pairs
* @param prefix prefix of each entry, which will be stripped
* @param resourceDescription description of the resource that the
* Map came from (for logging purposes)
* @throws BeansException if the bean definition could not be parsed or registered
*/
protected void registerBeanDefinition(String beanName, Map<?, ?> map, String prefix, String resourceDescription) throws BeansException {
String className = null;
String parent = null;
String scope = GenericBeanDefinition.SCOPE_SINGLETON;
boolean isAbstract = false;
boolean lazyInit = false;
ConstructorArgumentValues cas = new ConstructorArgumentValues();
MutablePropertyValues pvs = new MutablePropertyValues();
for (Map.Entry<?, ?> entry : map.entrySet()) {
String key = StringUtils.trimWhitespace((String) entry.getKey());
if (key.startsWith(prefix + SEPARATOR)) {
String property = key.substring(prefix.length() + SEPARATOR.length());
if (CLASS_KEY.equals(property)) {
className = StringUtils.trimWhitespace((String) entry.getValue());
} else if (PARENT_KEY.equals(property)) {
parent = StringUtils.trimWhitespace((String) entry.getValue());
} else if (ABSTRACT_KEY.equals(property)) {
String val = StringUtils.trimWhitespace((String) entry.getValue());
isAbstract = TRUE_VALUE.equals(val);
} else if (SCOPE_KEY.equals(property)) {
// Spring 2.0 style
scope = StringUtils.trimWhitespace((String) entry.getValue());
} else if (SINGLETON_KEY.equals(property)) {
// Spring 1.2 style
String val = StringUtils.trimWhitespace((String) entry.getValue());
scope = ((val == null || TRUE_VALUE.equals(val) ? GenericBeanDefinition.SCOPE_SINGLETON : GenericBeanDefinition.SCOPE_PROTOTYPE));
} else if (LAZY_INIT_KEY.equals(property)) {
String val = StringUtils.trimWhitespace((String) entry.getValue());
lazyInit = TRUE_VALUE.equals(val);
} else if (property.startsWith(CONSTRUCTOR_ARG_PREFIX)) {
if (property.endsWith(REF_SUFFIX)) {
int index = Integer.parseInt(property.substring(1, property.length() - REF_SUFFIX.length()));
cas.addIndexedArgumentValue(index, new RuntimeBeanReference(entry.getValue().toString()));
} else {
int index = Integer.parseInt(property.substring(1));
cas.addIndexedArgumentValue(index, readValue(entry));
}
} else if (property.endsWith(REF_SUFFIX)) {
// This isn't a real property, but a reference to another prototype
// Extract property name: property is of form dog(ref)
property = property.substring(0, property.length() - REF_SUFFIX.length());
String ref = StringUtils.trimWhitespace((String) entry.getValue());
// It doesn't matter if the referenced bean hasn't yet been registered:
// this will ensure that the reference is resolved at runtime.
Object val = new RuntimeBeanReference(ref);
pvs.add(property, val);
} else {
// It's a normal bean property.
pvs.add(property, readValue(entry));
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("Registering bean definition for bean name '" + beanName + "' with " + pvs);
}
// backwards compatibility reasons.
if (parent == null && className == null && !beanName.equals(this.defaultParentBean)) {
parent = this.defaultParentBean;
}
try {
AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(parent, className, getBeanClassLoader());
bd.setScope(scope);
bd.setAbstract(isAbstract);
bd.setLazyInit(lazyInit);
bd.setConstructorArgumentValues(cas);
bd.setPropertyValues(pvs);
getRegistry().registerBeanDefinition(beanName, bd);
} catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(resourceDescription, beanName, className, ex);
} catch (LinkageError err) {
throw new CannotLoadBeanClassException(resourceDescription, beanName, className, err);
}
}
use of org.springframework.beans.factory.config.RuntimeBeanReference in project spring-framework by spring-projects.
the class SimpleConstructorNamespaceHandler method decorate.
@Override
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
if (node instanceof Attr) {
Attr attr = (Attr) node;
String argName = StringUtils.trimWhitespace(parserContext.getDelegate().getLocalName(attr));
String argValue = StringUtils.trimWhitespace(attr.getValue());
ConstructorArgumentValues cvs = definition.getBeanDefinition().getConstructorArgumentValues();
boolean ref = false;
// handle -ref arguments
if (argName.endsWith(REF_SUFFIX)) {
ref = true;
argName = argName.substring(0, argName.length() - REF_SUFFIX.length());
}
ValueHolder valueHolder = new ValueHolder(ref ? new RuntimeBeanReference(argValue) : argValue);
valueHolder.setSource(parserContext.getReaderContext().extractSource(attr));
// handle "escaped"/"_" arguments
if (argName.startsWith(DELIMITER_PREFIX)) {
String arg = argName.substring(1).trim();
// fast default check
if (!StringUtils.hasText(arg)) {
cvs.addGenericArgumentValue(valueHolder);
} else // assume an index otherwise
{
int index = -1;
try {
index = Integer.parseInt(arg);
} catch (NumberFormatException ex) {
parserContext.getReaderContext().error("Constructor argument '" + argName + "' specifies an invalid integer", attr);
}
if (index < 0) {
parserContext.getReaderContext().error("Constructor argument '" + argName + "' specifies a negative index", attr);
}
if (cvs.hasIndexedArgumentValue(index)) {
parserContext.getReaderContext().error("Constructor argument '" + argName + "' with index " + index + " already defined using <constructor-arg>." + " Only one approach may be used per argument.", attr);
}
cvs.addIndexedArgumentValue(index, valueHolder);
}
} else // no escaping -> ctr name
{
String name = Conventions.attributeNameToPropertyName(argName);
if (containsArgWithName(name, cvs)) {
parserContext.getReaderContext().error("Constructor argument '" + argName + "' already defined using <constructor-arg>." + " Only one approach may be used per argument.", attr);
}
valueHolder.setName(Conventions.attributeNameToPropertyName(argName));
cvs.addGenericArgumentValue(valueHolder);
}
}
return definition;
}
use of org.springframework.beans.factory.config.RuntimeBeanReference in project spring-framework by spring-projects.
the class SimplePropertyNamespaceHandler method decorate.
@Override
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
if (node instanceof Attr) {
Attr attr = (Attr) node;
String propertyName = parserContext.getDelegate().getLocalName(attr);
String propertyValue = attr.getValue();
MutablePropertyValues pvs = definition.getBeanDefinition().getPropertyValues();
if (pvs.contains(propertyName)) {
parserContext.getReaderContext().error("Property '" + propertyName + "' is already defined using " + "both <property> and inline syntax. Only one approach may be used per property.", attr);
}
if (propertyName.endsWith(REF_SUFFIX)) {
propertyName = propertyName.substring(0, propertyName.length() - REF_SUFFIX.length());
pvs.add(Conventions.attributeNameToPropertyName(propertyName), new RuntimeBeanReference(propertyValue));
} else {
pvs.add(Conventions.attributeNameToPropertyName(propertyName), propertyValue);
}
}
return definition;
}
use of org.springframework.beans.factory.config.RuntimeBeanReference in project spring-framework by spring-projects.
the class BeanDefinitionParserDelegate method parseMapElement.
/**
* Parse a map element.
*/
public Map<Object, Object> parseMapElement(Element mapEle, BeanDefinition bd) {
String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE);
String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT);
ManagedMap<Object, Object> map = new ManagedMap<>(entryEles.size());
map.setSource(extractSource(mapEle));
map.setKeyTypeName(defaultKeyType);
map.setValueTypeName(defaultValueType);
map.setMergeEnabled(parseMergeAttribute(mapEle));
for (Element entryEle : entryEles) {
// Should only have one value child element: ref, value, list, etc.
// Optionally, there might be a key child element.
NodeList entrySubNodes = entryEle.getChildNodes();
Element keyEle = null;
Element valueEle = null;
for (int j = 0; j < entrySubNodes.getLength(); j++) {
Node node = entrySubNodes.item(j);
if (node instanceof Element) {
Element candidateEle = (Element) node;
if (nodeNameEquals(candidateEle, KEY_ELEMENT)) {
if (keyEle != null) {
error("<entry> element is only allowed to contain one <key> sub-element", entryEle);
} else {
keyEle = candidateEle;
}
} else {
// Child element is what we're looking for.
if (nodeNameEquals(candidateEle, DESCRIPTION_ELEMENT)) {
// the element is a <description> -> ignore it
} else if (valueEle != null) {
error("<entry> element must not contain more than one value sub-element", entryEle);
} else {
valueEle = candidateEle;
}
}
}
}
// Extract key from attribute or sub-element.
Object key = null;
boolean hasKeyAttribute = entryEle.hasAttribute(KEY_ATTRIBUTE);
boolean hasKeyRefAttribute = entryEle.hasAttribute(KEY_REF_ATTRIBUTE);
if ((hasKeyAttribute && hasKeyRefAttribute) || ((hasKeyAttribute || hasKeyRefAttribute)) && keyEle != null) {
error("<entry> element is only allowed to contain either " + "a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element", entryEle);
}
if (hasKeyAttribute) {
key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle);
} else if (hasKeyRefAttribute) {
String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error("<entry> element contains empty 'key-ref' attribute", entryEle);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(entryEle));
key = ref;
} else if (keyEle != null) {
key = parseKeyElement(keyEle, bd, defaultKeyType);
} else {
error("<entry> element must specify a key", entryEle);
}
// Extract value from attribute or sub-element.
Object value = null;
boolean hasValueAttribute = entryEle.hasAttribute(VALUE_ATTRIBUTE);
boolean hasValueRefAttribute = entryEle.hasAttribute(VALUE_REF_ATTRIBUTE);
boolean hasValueTypeAttribute = entryEle.hasAttribute(VALUE_TYPE_ATTRIBUTE);
if ((hasValueAttribute && hasValueRefAttribute) || ((hasValueAttribute || hasValueRefAttribute)) && valueEle != null) {
error("<entry> element is only allowed to contain either " + "'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle);
}
if ((hasValueTypeAttribute && hasValueRefAttribute) || (hasValueTypeAttribute && !hasValueAttribute) || (hasValueTypeAttribute && valueEle != null)) {
error("<entry> element is only allowed to contain a 'value-type' " + "attribute when it has a 'value' attribute", entryEle);
}
if (hasValueAttribute) {
String valueType = entryEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
if (!StringUtils.hasText(valueType)) {
valueType = defaultValueType;
}
value = buildTypedStringValueForMap(entryEle.getAttribute(VALUE_ATTRIBUTE), valueType, entryEle);
} else if (hasValueRefAttribute) {
String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error("<entry> element contains empty 'value-ref' attribute", entryEle);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(entryEle));
value = ref;
} else if (valueEle != null) {
value = parsePropertySubElement(valueEle, bd, defaultValueType);
} else {
error("<entry> element must specify a value", entryEle);
}
// Add final key and value to the Map.
map.put(key, value);
}
return map;
}
use of org.springframework.beans.factory.config.RuntimeBeanReference in project spring-framework by spring-projects.
the class DefaultListableBeanFactoryTests method testCustomTypeConverterWithBeanReference.
@Test
public void testCustomTypeConverterWithBeanReference() {
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
lbf.setTypeConverter(new CustomTypeConverter(nf));
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("myFloat", new RuntimeBeanReference("myFloat"));
ConstructorArgumentValues cav = new ConstructorArgumentValues();
cav.addIndexedArgumentValue(0, "myName");
cav.addIndexedArgumentValue(1, "myAge");
lbf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class, cav, pvs));
lbf.registerSingleton("myFloat", "1,1");
TestBean testBean = (TestBean) lbf.getBean("testBean");
assertEquals("myName", testBean.getName());
assertEquals(5, testBean.getAge());
assertTrue(testBean.getMyFloat().floatValue() == 1.1f);
}
Aggregations