B.4.Coding a BeanDefinitionParser
B.4. Coding a BeanDefinitionParser
As you can see, the namespace handler shown above registers so-called BeanDefinitionParsers
. A BeanDefinitionParser
in this case will be consulted if Spring the namespace handler encounters an XML element of the type that has been mapped to this specific bean definition parser (which is dateformat
in this case). In other words, the BeanDefinitionParser
is responsible for parsing one distinct top-level XML element defined in the schema. In the parser, we'll have access to the XML element (and its subelements) and the ParserContext
. The latter can be used to obtain a reference to for example the BeanDefinitionRegistry
as done in the example below.
package org.springframework.samples.xml;
import java.text.SimpleDateFormat;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
public class SimpleDateFormatBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
// create a RootBeanDefinition that will serve as configuration
// holder for the 'pattern' attribute and the 'lenient' attribute
RootBeanDefinition beanDef = new RootBeanDefinition();
beanDef.setBeanClass(SimpleDateFormat.class);
// never null
since the schema requires it
String pattern = element.getAttribute("pattern");
beanDef.getConstructorArgumentValues().addGenericArgumentValue(pattern);
String lenientString = element.getAttribute("lenient");
if (StringUtils.hasText(lenientString)) {
// won't throw exception if validation is turned on (boolean type set in schema)
beanDef.getPropertyValues().addPropertyValue("lenient", new Boolean(lenientString));
}
// retrieve the ID attribute that will serve as the bean identifier in the context
String id = element.getAttribute("id");
// create a bean definition holder to be able to register the
// bean definition with the bean definition registry
// (obtained through the ParserContext)
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDef, id);
// register the BeanDefinitionHolder (which contains the bean definition)
// with the BeanDefinitionRegistry
BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry());
return beanDef;
}
}
注意
In the example here, we're defining aBeanDefinition
and registering it with the BeanDefinitionRegistry
. Note that you don't necessarily have to register a bean definition with the registry or return a bean definition from the parse()
method. You are free to do whatever you want with the information given to you (i.e. the XML element) and the ParserContext
.The ParserContext
provides access to following properties
readerContext
- provides access to the bean factory and also to theNamespaceHandlerResolver
, which can optionally be used to resolve nested namespaces.parserDelegate
- controlling component that drives the parsing of (parts of) the configuration file. Typically you don't need to access this.registry
- theBeanDefinitionRegistry
that allows you to register newly createdBeanDefinition
instances with.nested
- indicates whether or the XML element that is currently being processed is part of a outer bean definition (in other words, it's defined similar to traditional inner-beans).