dubbo自定义标签

本文介绍了如何实现Dubbo中的自定义XML标签。首先概述了研究Dubbo自定义标签的原因,接着详细讲述了XML标签的Schema定义,包括创建`.xsd`规范文件。然后讨论了自定义标签的解析处理,涉及`NamespaceHandlerSupport`和`BeanDefinitionParser`类在解析和注册bean到Spring容器中的作用。最后,文章以一个简单的自定义标签示例作结,并指出复杂标签的实现原理与此相似。

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

一概述

      最近想看看dubbo的实现原理,刚入手代码相关文档提到它与spring框架无缝对接,所以对里面的自定义标签有了兴趣。在spring的配置文件中也经常看到一些很特殊的标签比如spring的事物标签<tx:开头,面向切面处理的<aop:,这里来研究下做个自己的标签怎么玩的。

二xml标签Schema

   要写自己的标签肯定需要有xml的标签规范,所以需要一个schema文件,后缀是.xsd的文件。具体的规范如何编写可以参考 http://www.w3school.com.cn/schema 里面有详细的描述。这里我自己建了一个tag.xsd文件,名字可以自己随意命名,但是后缀必须是xsd的。内容如下:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
               targetNamespace="http://aaaa/schema/tag"
                         xmlns="http://aaaa/schema/tag"
               elementFormDefault="qualified">

    <xs:element name="bean">
            <xs:complexType>
                <xs:attribute name="id" type="xs:string"></xs:attribute>
                <xs:attribute name="className" type="xs:string" use="required"></xs:attribute>
                <xs:attribute name="scope" type="xs:string" use="optional"></xs:attribute>
            </xs:complexType>
    </xs:element>

</xs:schema>
xml的根节点的写法是我从http://www.w3school.com.cn/schema 中拷贝的例子写法。但根节点Schema中的targetNamespace,xmlns属性值是自定义的,之前看别人的写法都是固定的http开头写法以为是需要去某处注册下的http地址,后来自己尝试以后发现这里的属性值只是一个字符串。但是这里的字符串内容必须和spring.schemas文件里面的写法一致。到这里我们的schemas文件已经编写好了,还需要将改规范发布让spring知道有这个规范。这步需要在资源根目录下建META-INF文件夹,在里面建一个spring.schemas的文件,里面有个键值对,内如下:

http\://aaaa/schema/tag/tag.xsd=conf/tag.xsd
这个key就是schema中的targetNamespace标记值,value就是schema文件的保存路径。这时已经在spring中发布了xm的规范,我们开始在xml中使用自己定义的标签。如下:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aa="http://aaaa/schema/tag"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://aaaa/schema/tag
      http://aaaa/schema/tag/tag.xsd">

        <aa:bean id="car" className="com.client.haha" scope="1"></aa:bean>
        <aa:bean id="user" className="com.client.ClientTest" scope="1"></aa:bean>

</beans>
在xml中使用自己定义的标签需要引入自定义的规范,如以上的第3行和6,7行的头引入。注意第三行中的aa,这个是可以随意定义的,它就是标签的使用标记。正常引入以后就可以在XML中使用相关的bean标签了。这里要注意相关资源的存放路径,如下图:



三自定义标签解析处理

   到这里我们的自定义标签已经在spring中正常发布了,现在需要能解析自定义标签,并将解析后的bean对象注册到spring容器中。主要涉及到两个类,这两个类都是spring容器中的,需要添加相关依赖。NamespaceHandlerSupport,BeanDefinitionParser。需要通过指定自定义的NamespaceHandlerSupport指定BeanDefinitionParser将自定义的标签进行解析。

public class TagNamespaceHandler extends NamespaceHandlerSupport {


    public void init() {
        registerBeanDefinitionParser("bean", new TagBeanDefinitionParser());
    }
}
TagNamespaceHandler类为自定namespaceHandler,里面的“bean”就是我们自定义的标签名字,指明遇到bean标签需要TagBeanDefinitionParser类来解析处理。在spring.handlers串联了自定义的namespaceHandler和schemas,写法如下:

http\://aaaa/schema/tag=com.tag.TagNamespaceHandler

TagBeanDefinitionParser类解析自定义标签处理,并将解析后的RootBeanDefinition注册进入sprin容器中。

public class TagBeanDefinitionParser implements BeanDefinitionParser {


    public BeanDefinition parse(Element element, ParserContext parserContext) {


        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(TagBean.class);
        beanDefinition.setLazyInit(false);
        String id=element.getAttribute("id");
        String className=element.getAttribute("className");

        beanDefinition.getPropertyValues().add("id",id);
        beanDefinition.getPropertyValues().add("className",className);

        parserContext.getRegistry().registerBeanDefinition(id,beanDefinition);


        return beanDefinition;
    }
}

标签解析后的数据存储对象

public class TagBean {


    private String id;
    private String className;

    public String getId() {
        return id;
    }

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

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }
}

加载xml文件,并获取spring容器中的自定义bean容器对象处理

public class TagMain {



    public static void main(String[] ags){
        String xml = "classpath:applicationContext.xml";
        ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { xml });
        TagBean tagName=(TagBean)context.getBean("user");
        TagBean carName=(TagBean)context.getBean("car");
        System.out.println(tagName.getClassName());
        System.out.println(carName.getClassName());


    }
}

执行以上的main函数会加载spring容器,输出xml中的配置数据。

com.client.ClientTest
com.client.haha

四总结

      这样一个简单的自定义标签就做完了,与复杂的标签相比在schemas文件编写复杂一些,但主体的思路是一致的。那么我们常见的spring中用的到<aop:  ,<tx:标签也应该是这么来做的,如果想知道NamespaceHandlerSupport,BeanDefinitionParser的实现原理可以看看spring的源码。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值