Spring源码解析系列文章(X)——扩展Spring自定义标签

目录

1、创建承载自定义标签属性的类

2、创建XSD

3、创建解析XSD文件自定义标签的类

4、创建Handler

5、编写 spring.handlers 和 spring.schemas文件

spring.handlers

spring.schemas

6、引入自定义标签

7、验证


1、创建承载自定义标签属性的类

package thinking.in.spring.boot.samples.spring5.customlabel;

/**
 * 创建承载自定义标签属性的类
 */
public class CustomLabel {

    private String id;
    private String name;
    private String value;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

2、创建XSD

在maven工程 resources/META-INF/ 下创建 spring-custom.xsd 文件,内容如下

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.rh.com/schema/customLabel"
xmlns:tns="http://www.rh.com/schema/customLabel"
elementFormDefault="qualified">
    <element name="mybean">
        <complexType>
            <attribute name="id" type="string"/>
            <attribute name="name" type="string"/>
            <attribute name="value" type="string"/>
        </complexType>
    </element>
    <element name="tag2">
        <complexType>
            <attribute name="id" type="string"/>
            <attribute name="name" type="string"/>
            <attribute name="value" type="string"/>
        </complexType>
    </element>
</schema>

3、创建解析XSD文件自定义标签的类

创建 CustomLabelBeanDefinitionParser 类,此类继承了AbstractSingleBeanDefinitionParser ,用于解析XSD自定义标签

package thinking.in.spring.boot.samples.spring5.customlabel;

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 CustomLabelBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    // Element 对应的类
    protected Class getBeanClass(Element element) {
        return CustomLabel.class;
    }

    // 从 Element 中解析并提取对应的元素
    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        String id = element.getAttribute("id");
        String name = element.getAttribute("name");
        String value = element.getAttribute("value");
        /**
         * 将提取的数据放入到 BeanDefinitionBuilder中,等完成所有bean的解析后统一注册到 BeanFactory
         */
        if (StringUtils.hasText(id)) {
            bean.addPropertyValue("id", id);
        }
        if (StringUtils.hasText(name)) {
            bean.addPropertyValue("name", name);
        }
        if (StringUtils.hasText(value)) {
            bean.addPropertyValue("value", value);
        }
    }
}

4、创建Handler

扩展 NamespaceHandlerSupport,目的是将自定义标签标注的类注册到 Spring 容器。

package thinking.in.spring.boot.samples.spring5.customlabel;

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

public class CustomLabelNamespaceHandler extends NamespaceHandlerSupport{
    @Override
    public void init() {
        // 一个标签对应一个解析器
        registerBeanDefinitionParser("mybean", new CustomLabelBeanDefinitionParser());
        registerBeanDefinitionParser("tag2", new CustomLabelBeanDefinitionParser());
    }
}

5、编写 spring.handlers 和 spring.schemas文件

文件创建在 resources/META-INF/ 目录下。

spring.handlers

文件内容如下

http\://www.rh.com/schema/customLabel=thinking.in.spring.boot.samples.spring5.customlabel.CustomLabelNamespaceHandler

spring.schemas

文件内容如下

http\://www.rh.com/schema/customLabel.xsd=META-INF/spring-custom.xsd

6、引入自定义标签

引入自定义标签到Spring配置文件,配置文件如下

<?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:customLabel="http://www.rh.com/schema/customLabel"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.rh.com/schema/customLabel
        http://www.rh.com/schema/customLabel.xsd">

    <!--<bean id="user" class="thinking.in.spring.boot.samples.spring5.bean.User">-->
        <!--<property name="name" value="zhangsan"/>-->
        <!--<property name="id" value="1"/>-->
    <!--</bean>-->

    <customLabel:mybean id="rh" name="rh" value="自定义标签一" />
    <customLabel:tag2 id="tag2" name="tag2" value="自定义标签2" />
</beans>

7、验证

创建Spring引导类,测试自定义标签是否配置成功

XmlBeanFactoryBootstrap 引导类如下

package thinking.in.spring.boot.samples.spring5.bootstrap;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import thinking.in.spring.boot.samples.spring5.customlabel.CustomLabel;
import thinking.in.spring.boot.samples.spring5.bean.User;

public class XmlBeanFactoryBootstrap {

    public static void main(String[] args) {
        DefaultListableBeanFactory defaultListableBeanFactory = new XmlBeanFactory(new ClassPathResource("application-context.xml"));
//        User user = defaultListableBeanFactory.getBean(User.class);
//        System.out.println(user);

        CustomLabel customLabel = (CustomLabel) defaultListableBeanFactory.getBean("rh");
        System.out.println(customLabel.getName() + " == " + customLabel.getValue());
        CustomLabel tag2 = (CustomLabel) defaultListableBeanFactory.getBean("tag2");
        System.out.println(tag2.getName() + " == " + tag2.getValue());
    }
}

运行结果

三月 23, 2020 2:28:29 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [application-context.xml]
rh == 自定义标签一
tag2 == 自定义标签2
发布了178 篇原创文章 · 获赞 47 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/ruanhao1203/article/details/105048158
今日推荐