In addition to the schema, we need a NamespaceHandler
that will parse all elements of this specific namespace Spring encounters
while parsing configuration files. The NamespaceHandler
should in our case take care of the parsing of the myns:dateformat
element.
The NamespaceHandler
interface is pretty simple in that
it features just three methods:
init()
- allows for initialization of
the NamespaceHandler
and will be called by Spring
before the handler is used
BeanDefinition parse(Element, ParserContext)
-
called when Spring encounters a top-level element (not nested inside a bean definition
or a different namespace). This method can register bean definitions itself and/or
return a bean definition.
BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext)
-
called when Spring encounters an attribute or nested element of a different namespace.
The decoration of one or more bean definitions is used for example with the
out-of-the-box scopes Spring 2.0 supports.
We'll start by highlighting a simple example, without using decoration, after which
we will show decoration in a somewhat more advanced example.
Although it is perfectly possible to code your own
NamespaceHandler
for the entire namespace
(and hence provide code that parses each and every element in the namespace),
it is often the case that each top-level XML element in a Spring XML
configuration file results in a single bean definition (as in our
case, where a single <myns:dateformat/>
element
results in a single SimpleDateFormat
bean definition).
Spring features a number of convenience classes that support this scenario.
In this example, we'll make use the NamespaceHandlerSupport
class:
package org.springframework.samples.xml;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());
}
}
The observant reader will notice that there isn't actually a whole lot of
parsing logic in this class. Indeed... the NamespaceHandlerSupport
class has a built in notion of delegation. It supports the registration of any number
of BeanDefinitionParser
instances, to which it will delegate
to when it needs to parse an element in it's namespace. This clean separation of concerns
allows a NamespaceHandler
to handle the orchestration
of the parsing of all of the custom elements in it's namespace,
while delegating to BeanDefinitionParsers
to do the grunt work of the
XML parsing; this means that each BeanDefinitionParser
will
contain just the logic for parsing a single custom element, as we can see in the next step