Spring custom namespace

Spring custom namespace

GitHub Demo address

Explanation

When Spring parses the tags in the xml file, it will distinguish whether the current tag is four basic tags (import, alias, bean and beans) or a custom tag. If it is a custom tag, it will parse the current according to the logic of the custom tag s Mark.

Starting from version 2.0, the Spring framework provides an extension mechanism for defining beans based on the Schema-style Spring XML format. The introduction of Schema-based XML is to simplify the traditional XML configuration form.

Through the definition of Schema, some configuration forms that originally need to be defined by the definition of several beans or a combination of complex beans are presented in another simple and readable configuration form.

Schema-based XML consists of three parts:

  1. namespace-has a very clear logical classification
  2. element-has very clear process semantics
  3. attributes-has very simple configuration options

E.g:

<mvc:annotation-driven />

The meaning of this configuration is to realize Annotation-driven configuration in the space of mvc.

among them,

  • mvcIndicates the effective range of the configuration,
  • annotation-drivenIt expresses a dynamic process, the actual logical meaning is: the implementation of the entire SpringMVC is based on the Annotation mode, please register the relevant behavior mode for me.

customize

The following will explain how to write custom XML bean definition parsing and integrate this parsing into the Spring IOC container.

In the following content we will mention an important concept is the bean definition. In fact, there is an important concept in Spring is the bean. And the BeanDefinition object is the corresponding label after parsing the object.

You can create a new xml configuration extension using the following short answer steps:

  • Authoring an XML schema to describe your custom element (s)
  • Coding a custom NamespaceHandler implementation (this is a very simple step, don't worry)
  • Coding one or more BeanDefinitionParse implementation (this is the most important)
  • Registeringr register the above to Spring (this is also a short answer step)

Examples

We need to create an XML extension (custom xml element) that allows us to configure the SimpleDateFormat object (in the java.text package) in a simple way. Finally, we can define a simpleDateFormat type bean definition as follows:

    <myns:dateformat id="dateFormat"
                     pattern="yyyy-MM-dd HH:mm"
                     lenient="true"/>

1. Create a configuration

Create a file in the resources of the project:

myns.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.mycompany.com/schema/myns"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:beans="http://www.springframework.org/schema/beans"
            targetNamespace="http://www.mycompany.com/schema/myns"
            elementFormDefault="qualified"
            attributeFormDefault="unqualified">

    <xsd:import namespace="http://www.springframework.org/schema/beans"/>

    <xsd:element name="dateformat">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="lenient" type="xsd:boolean"/>
                    <xsd:attribute name="pattern" type="xsd:string" use="required"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

The above schema will be used to configure the SimpleDateFormat object.

Used directly in a xml application context file <myns:dateformat />.

<myns:dateformat id="dateFormat"
    pattern="yyyy-MM-dd HH:mm"
    lenient="true"/>

Note: The XML fragment above is essentially the same as the XML fragment below.

<bean id="dateFormat" class="java.text.SimpleDateFormat">
    <constructor-arg value="yyyy-HH-dd HH:mm"/>
    <property name="lenient" value="true"/>
</bean>

2. Write a namespace processor

For the above schema, we need NamespaceHandlerto parse all of the specific namespaceconfiguration files encountered by Spring elements. This NamespaceHandlerwill care about the parsing myns:dateformatelements.

The NamespaceHandler interface is relatively simple, and it includes three important methods.

  1. init() -NamespaceHandler will be instantiated before spring uses handler
  2. BeanDefinition parse(Element, ParseContext) -When Spring encounters the top-level element (that is, myms) defined above, it will be called.This method can register bean definitions and can return a bean definition.
  3. BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext) -Spring will be called when it encounters an attribute or element embedded in the namespace.

MyNamespaceHandler.java

package com.jeiker.namespace;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class MyNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());
    }

}

3. Parse custom xml elements

The responsibility of BeanDefinitionParser is to parse XML elements that define the schema at the top-level. During the parsing process, we must access the XML elements, so we can parse our custom XML content.

SimpleDateFormatBeanDefinitionParser.java

package com.jeiker.namespace;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

import java.text.SimpleDateFormat;

public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    @Override
    protected Class getBeanClass(Element element) {
        return SimpleDateFormat.class;
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        // this will never be null since the schema explicitly requires that a value be supplied
        String pattern = element.getAttribute("pattern");
        bean.addConstructorArgValue(pattern);

        // this however is an optional property
        String lenient = element.getAttribute("lenient");
        if (StringUtils.hasText(lenient)) {
            bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
        }
    }

}

note:

  1. We use AbstractSingleBeanDefinitionParser provided by Spring to handle some basic work of creating a single BeanDefinition.
  2. We rewrote the doParse method of the AbstractSingleBeanDefinitionParser parent class to implement our own logic for creating a single-type BeanDefinition.

4. Register the schema and handler in Spring

4.1 Registration schema

Create in resources

META-INF/spring.schemas

http\://www.mycompany.com/schema/myns/myns.xsd=xml/myns.xsd

4.2 Register handler

Create in resources

META-INF/spring.handlers

http\://www.mycompany.com/schema/myns=com.jeiker.namespace.MyNamespaceHandler

5. Test

5.1 Configure schema-beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:myns="http://www.mycompany.com/schema/myns"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd">

    <myns:dateformat id="dateFormat"
                     pattern="yyyy-MM-dd HH:mm"
                     lenient="true"/>

</beans>

5.2 Test category

package com.jeiker.namespace;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.text.SimpleDateFormat;
import java.util.Date;

public class SchemaBeanDefinitionTest {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("schema-beans.xml");
        SimpleDateFormat dateFormat = context.getBean("dateFormat", SimpleDateFormat.class);
        System.out.println("-------------------gain object--------------------");
        System.out.println(dateFormat);
        String dateStr = dateFormat.format(new Date());
        System.out.println(dateStr);
    }
}
Published 420 original articles · 143 thumbs up · 890,000 views

Guess you like

Origin blog.csdn.net/jeikerxiao/article/details/96285031