Spring自定义标签

在日常开发中,我们经常使用Spring、Dubbo、Mybatis等框架的标签来配置我们的应用。那么这些第三方的框架如何被Spring解析到的?本文将实现一个自定义标签的案例。学习来Spring自定义标签之后,我们也能自定义标签,在阅读其他框架集成Spring框架的时候也能知道其原理

  • 首先我们看看Spring源代码中spring-context包
    在这里插入图片描述

通过查看spring-context源代码可以看到代码中定义来大量的dtd和xsd文件。主要是用来约束我们的XML的规范,spring.handlers和spring.schemas文件主要是配置xml文件的位置和解析XML文件。

自定义标签的步骤

1.自定义一个xsd文件

这个xsd文件用来约束xml的标签,要让这个xsd文件生效,需要在项目的resource/META-INF配置2个文件.

2.定义spring.schemas

主要用一个url来映射第一步配置好的文件,告诉spring自定好的xsd的位置.

3.定义spring.handles

这个配置文件用来配置解析自定义标签的类

4.创建schema的解析类

定义解析类,需要继承NamespaceHandlerSupport。告诉Spring我们的schma处理器。可以解析标签

5.注册每个标签的解析类

标签对应的解析类,需要实现BeanDefinitionParser接口或者继承AbstractSingleBeanDefinitionParser

依照上面的步骤自定义标签以实现bean注册
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="http://www.qianyi.com/schema/company" targetNamespace="http://www.qianyi.com/schema/company"
            elementFormDefault="qualified">
    <xsd:element name="company">
        <xsd:complexType>
            <xsd:attribute name="id" type="xsd:string" />
            <xsd:attribute name="name" type="xsd:string" />
            <xsd:attribute name="address" type="xsd:string" />
        </xsd:complexType>
    </xsd:element>
</xsd:schema>
创建文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义
package person.me.parser;

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 person.me.model.Company;

public class CompanyBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    @Override
    protected Class getBeanClass(Element element) {
        return Company.class;
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String id= element.getAttribute("id");
        String name= element.getAttribute("name");
        String address= element.getAttribute("address");
        if(StringUtils.hasText(id)){
            builder.addPropertyValue("id", id);
        }
        if(StringUtils.hasText(name)){
            builder.addPropertyValue("name", name);
        }
        if(StringUtils.hasText(name)){
            builder.addPropertyValue("address", name);
        }
    }
}
创建Handler文件,扩展自NamespaceHandlerSupport,将组件注册到Spring容器中。
package person.me.handle;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import person.me.parser.CompanyBeanDefinitionParser;
import person.me.parser.UserBeanDefinitionParser;

public class MyUserNamespaceHandler extends NamespaceHandlerSupport{

    @Override
    public void init() {
        registerBeanDefinitionParser("user",new UserBeanDefinitionParser());
        registerBeanDefinitionParser("company",new CompanyBeanDefinitionParser());
    }
}
定义解析文件

spring.handlers文件:

http\://www.qianyi.com/schema/user=person.me.handle.MyUserNamespaceHandler
http\://www.qianyi.com/schema/company=person.me.handle.MyUserNamespaceHandler

spring.schemas文件:

http\://www.qianyi.com/schema/user.xsd=META-INF/spring-user.xsd
http\://www.qianyi.com/schema/company.xsd=META-INF/spring-company.xsd
测试的配置文件
<?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:user="http://www.qianyi.com/schema/user"
       xmlns:compay="http://www.qianyi.com/schema/company"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.qianyi.com/schema/user http://www.qianyi.com/schema/user.xsd
        http://www.qianyi.com/schema/company http://www.qianyi.com/schema/company.xsd">

    <user:user id="id" name="qianyi"/>
    <compay:company id="company" name="公司名称" address="测试地址"/>
</beans>
测试类:
package person.me;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import person.me.model.Company;
import person.me.model.User;

public class TagTest {

    @Test
    public void test(){
        ApplicationContext beans=new ClassPathXmlApplicationContext("classpath:application-customtag.xml");
        User user=(User)beans.getBean("id");
        System.out.println(user);

        Company company=(Company)beans.getBean("company");
        System.out.println(company.getAddress());
    }
}
测试结果
User{id='id', name='qianyi'}
公司名称

具体代码查看:
https://github.com/cqqianyi/spring-source-study/tree/main/spring-customer-tags

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值