Spring源码导读之自定义解析xml

本文介绍如何自定义XML解析器与Spring框架集成,通过定义名称空间、Schema及NamespaceHandler,实现对自定义标签的解析,加载特定的Bean。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义解析xml案例,其原理见:NameSpaceHandler

public class People {
    private String name;

    private String gender;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

我们希望自定义一个名称空间"pp",我们自定义解析其people标签,加载这个People 这个 bean。

<?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:pp="http://www.springframework.org/schema/pp"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/pp
        http://www.springframework.org/schema/beans/spring-pp-3.1.xsd
        ">
    <!--
   <bean class="com.jack.ascp.purchase.app.test.spring.parse.xml.People" pp:property = "name:jpl,gender:man">
    </bean>
    -->
    <pp:people>
        <pp:property>name:jpl,gender:man</pp:property>
    </pp:people>

</beans>

定义其名称空间为"http://www.springframework.org/schema/pp",对应schema文件http://www.springframework.org/schema/beans/spring-pp-3.1.xsd,由于这个文件是我们自定义的,网络上并没有,因此我们为其建一个本地文件:custom-spring-pp.xsd

custom-spring-pp.xsd:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<xsd:schema xmlns="http://www.springframework.org/schema/pp"
		xmlns:xsd="http://www.w3.org/2001/XMLSchema"
		targetNamespace="http://www.springframework.org/schema/pp">
	
	<xsd:attribute name="property" type="xsd:string"/>

	<xsd:element name="property" type="xsd:string"/>
	<!-- 定义一个element叫people -->
	<xsd:element name="people">
		<!-- 它是一个复杂类型 -->
		<xsd:complexType>
			<!-- 它里面包含一个序列 -->
			<xsd:sequence>
				<!-- 有一个property属性作为孩子成员 -->
				<xsd:element ref="property"/>
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>
</xsd:schema>

在spring.schemas文件中配置custom-spring-pp.xsd为本地schema文件。

http\://www.springframework.org/schema/beans/spring-pp-3.1.xsd=custom-spring-pp.xsd

然后为这个名称空间配置它的NamespaceHandler

public class PPNameSpaceHandler implements NamespaceHandler {

    private final static String PROPERTY = "property";

    private final static String PEOPLE = "people";
    @Override
    public void init() {

    }

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        if (PEOPLE.equals(element.getLocalName())) {
            GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
            beanDefinition.setBeanClassName(People.class.getName());

            String beanName = parserContext.getReaderContext().generateBeanName(beanDefinition);

            NodeList childNodes = element.getChildNodes();

            for (int i = 0; i < childNodes.getLength(); i++) {
                Node node = childNodes.item(i);
                if (PROPERTY.equals(node.getLocalName())) {
                    String value = node.getFirstChild().getNodeValue().trim();
                    String[] pairs = StringUtils.tokenizeToStringArray(value, ",");
                    for (String pair : pairs) {
                        String[] attrs = StringUtils.tokenizeToStringArray(pair, ":");
                        PropertyValue pv = new PropertyValue(attrs[0], attrs[1]);
                        beanDefinition.getPropertyValues().addPropertyValue(pv);
                    }
                }
            }
            parserContext.getRegistry().registerBeanDefinition(beanName, beanDefinition);

        }
        return null;
    }

    @Override
    public BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext) {
        if (PROPERTY.equals(source.getLocalName())) {
            String value = source.getNodeValue().trim();
            String[] pairs = StringUtils.tokenizeToStringArray(value, ",");
            for (String pair : pairs) {
                String[] attrs = StringUtils.tokenizeToStringArray(pair, ":");
                PropertyValue pv = new PropertyValue(attrs[0], attrs[1]);
                definition.getBeanDefinition().getPropertyValues().addPropertyValue(pv);
            }
        }
        return definition;
    }
}

接着是我们的测试类:

public class PPNameSpaceHandlerDebug {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("custom_xml_parse_demo.xml");
        People people = context.getBean(People.class);
        System.out.println(people.getGender());
        System.out.println(people.getName());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值