Provide custom configuration support based on Spring Extensible Schema (transfer)

 

Reprinted from: http://blog.csdn.net/cutesource/article/details/5864562

 

In many cases, we need to provide configurable support for the system. The simple method can be configured directly based on the standard beans of spring, but when the configuration is more complex or requires more rich control, it will be very clumsy. The general practice is to parse the defined xml file in the original ecological way, and then convert it into a configuration object. Of course, this method can solve all problems, but it is cumbersome to implement, especially when the configuration is very complex, the parsing work is a burden that has to be considered. Spring provides support for extensible Schema, which is a good compromise. Completing a custom configuration generally requires the following steps:

Designing Configuration Properties and JavaBeans
Write XSD file
Write NamespaceHandler and BeanDefinitionParser to complete the parsing work
Write spring.handlers and spring.schemas to concatenate all the parts
Apply in bean file
The following is a small example to actually combat the above process

1) Design configuration properties and JavaBeans

First of all, of course, the configuration items must be designed and modeled by JavaBean. In this example, the People entity needs to be configured, and the configuration attributes name and age (id is required by default)

[Java] view plain copy
public class People {  
    private String id;  
    private String name;  
    private Integer age;  
}  
2) Write the XSD file

Write an XSD file for the configuration item designed in the previous step. XSD is the definition file of the schema. The input and parsing output of the configuration are based on the XSD contract. In this example, the XSD is as follows:

[xhtml] view plain copy
<?xml version="1.0" encoding="UTF-8"?>  
<xsd:schema   
    xmlns="http://blog.csdn.NET/cutesource/schema/people"  
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"   
    xmlns:beans="http://www.springframework.org/schema/beans"  
    targetNamespace="http://blog.csdn.Net/cutesource/schema/people"  
    elementFormDefault="qualified"   
    attributeFormDefault="unqualified">  
    <xsd:import namespace="http://www.springframework.org/schema/beans" />  
    <xsd:element name="people">  
        <xsd:complexType>  
            <xsd:complexContent>  
                <xsd:extension base="beans:identifiedType">  
                    <xsd:attribute name="name" type="xsd:string" />  
                    <xsd:attribute name="age" type="xsd:int" />  
                </xsd:extension>  
            </xsd:complexContent>  
        </xsd:complexType>  
    </xsd:element>  
</xsd:schema>  
The specific meaning of each attribute of xsd:schema will not be explained too much, please refer to http://www.w3school.com.cn/schema/schema_schema.asp

<xsd:element name="people"> corresponds to the name of the configuration item node, so people will be used as the node name to refer to this configuration in the application

<xsd:attribute name="name" type="xsd:string" /> and <xsd:attribute name="age" type="xsd:int" /> correspond to the two attribute names of the configuration item people, so in The application can configure two attributes, name and age, which are of type string and int respectively.

After completion, the xsd needs to be stored in the classpath, usually in the META-INF directory (in this example, it is placed in this directory)

3) Write NamespaceHandler and BeanDefinitionParser to complete the parsing work

The following needs to complete the parsing work, which will use the concepts of NamespaceHandler and BeanDefinitionParser. Specifically, NamespaceHandler will find a BeanDefinitionParser according to the schema and node name, and then the BeanDefinitionParser will complete the specific parsing work. Therefore, it is necessary to complete the implementation classes of NamespaceHandler and BeanDefinitionParser respectively. Spring provides default implementation classes NamespaceHandlerSupport and AbstractSingleBeanDefinitionParser. The simple way is to inherit these two classes. This example is done in this way:

[java] view plain copy
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;  
public class MyNamespaceHandler extends NamespaceHandlerSupport {  
    public void init() {  
        registerBeanDefinitionParser("people", new PeopleBeanDefinitionParser());  
    }  
}  
Among them, registerBeanDefinitionParser("people", new PeopleBeanDefinitionParser()); is used to associate the node name with the parsing class. When the people configuration item is referenced in the configuration, the PeopleBeanDefinitionParser will be used to parse the configuration. PeopleBeanDefinitionParser is the parsing class in this example:

[java] view plain copy
import org.springframework.beans.factory.support.BeanDefinitionBuilder;  
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;  
import org.springframework.util.StringUtils;  
import org.w3c.dom.Element;  
public class PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {  
    protected Class getBeanClass(Element element) {  
        return People.class;  
    }  
    protected void doParse(Element element, BeanDefinitionBuilder bean) {  
        String name = element.getAttribute("name");  
        String age = element.getAttribute("age");  
        String id = element.getAttribute("id");  
        if (StringUtils.hasText(id)) {  
            bean.addPropertyValue("id", id);  
        }  
        if (StringUtils.hasText(name)) {  
            bean.addPropertyValue("name", name);  
        }  
        if (StringUtils.hasText(age)) {  
            bean.addPropertyValue("age", Integer.valueOf(age));  
        }  
    }  
}  
Among them, element.getAttribute is to get the attribute value from the configuration, and bean.addPropertyValue is to put the attribute value into the bean.

4) Write spring.handlers and spring.schemas to concatenate all components

After walking down the above steps, you will find that the developed handler and xsd cannot be perceived by the application, so it is impossible to incorporate the previous work into the system. Spring provides spring.handlers and spring.schemas. Two configuration files to do this work, these two files need to be written by ourselves and put into the META-INF folder, the addresses of these two files must be META-INF/spring.handlers and META-INF/spring. schemas, spring will load them by default. In this example, spring.handlers is as follows:

http/://blog.csdn.net/cutesource/schema/people=study.schemaExt.MyNamespaceHandler

The above means that when a schema reference named "http://blog.csdn.net/cutesource/schema/people" is used, the parsing will be done through study.schemaExt.MyNamespaceHandler

spring.schemas looks like this:
http/://blog.csdn.net/cutesource/schema/people.xsd=META-INF/people.xsd

The above is to load the xsd file

5) Apply in Bean file

So far, a simple custom configuration has been completed and can be used in specific applications. The usage method is very simple, similar to configuring an ordinary spring bean, but it needs to be customized based on our schema. In this example, the reference method is as follows:

[xhtml] view plain copy
<?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:cutesource="http://blog.csdn.net/cutesource/schema/people"  
    xsi:schemaLocation="  
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
http://blog.csdn.net/cutesource/schema/people http://blog.csdn.net/cutesource/schema/people.xsd">  
    <cutesource:people id="cutesource" name="袁志俊" age="27"/>  
</beans>  
Where xmlns:cutesource="http://blog.csdn.net/cutesource/schema/people" is used to specify the custom schema, and xsi:schemaLocation is used to specify the xsd file. <cutesource:people id="cutesource" name="zhijun.yuanzj" age="27"/> is a specific example of custom configuration usage.

Finally, we can use the basic bean loading method to load our custom configuration object in a specific program, such as:

[java] view plain copy
ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");  
People p = (People)ctx.getBean("cutesource");  
System.out.println(p.getId());  
System.out.println(p.getName());  
System.out.println(p.getAge());  
will output:

cutesource
Yuan Zhijun
27

 

The above is a practical process of providing custom configuration support based on Spring's extensible Schema. Some complex applications and skills have yet to be explored.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326525620&siteId=291194637