首页 > 代码库 > Spring的自定义标签

Spring的自定义标签

当Spring拿到一个元素时首先要做的是根据命名空间进行解析,如果是默认的命名空间,则使用parseDefaultElement方法进行元素解析,否则使用parseCustom Element方法进行解析。

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

    public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
        String namespaceUri = getNamespaceURI(ele);
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        }
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }

自定义标签的使用

扩展Spring自定义标签配置大致需要以下几个步骤(前提是要把Spring的Core包加入项目中)。

  1. 创建一个需要扩展的组件。
  2. 定义一个XSD文件描述组件内容。
  3. 创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义。
  4. 创建一个Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器。
  5. 编写Spring.handlers和Spring.schemas文件。

现在我们就按照上面的步骤一步步地体验自定义标签的过程。

第一步:

public class TestBean {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "TestBean{" +
                "name=‘" + name + ‘\‘‘ +
                ‘}‘;
    }
}

第二步:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>  
<xsd:schema xmlns="http://code.alibabatech.com/schema/dubbo"  
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"   
        targetNamespace="http://code.alibabatech.com/schema/dubbo">  
  
        <xsd:element name="custom" type="customType">  
        </xsd:element>  
        <xsd:complexType name="customType">  
                <xsd:attribute name="id" type="xsd:ID">  
                </xsd:attribute>  
                <xsd:attribute name="name" type="xsd:string">  
                </xsd:attribute>  
        </xsd:complexType>  
  
</xsd:schema> 

第三步:

import org.springframework.beans.factory.config.BeanDefinition;  
import org.springframework.beans.factory.support.RootBeanDefinition;  
import org.springframework.beans.factory.xml.BeanDefinitionParser;  
import org.springframework.beans.factory.xml.ParserContext;  
import org.w3c.dom.Element;  
  
public class TestCustomBeanDefinitionParser implements BeanDefinitionParser {  
  
    public BeanDefinition parse(Element element, ParserContext parserContext) {  
  
        String id = element.getAttribute("id");  
        String name = element.getAttribute("name");  
  
        RootBeanDefinition beanDefinition = new RootBeanDefinition();  
        beanDefinition.setBeanClass(TestBean.class);  
        beanDefinition.getPropertyValues().addPropertyValue("name", name);  
        parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);  
  
        return beanDefinition;  
    }  
}  

第四步:

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;  
public class TestNamespaceHandler extends NamespaceHandlerSupport {  
    public void init() {  
        registerBeanDefinitionParser("custom", new TestCustomBeanDefinitionParser());  
    }  
}  

第五步:

spring.handlers:
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
spring.schemas:
http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.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:dubbo="http://code.alibabatech.com/schema/dubbo"  
    xsi:schemaLocation="  
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">  
          
        <dubbo:custom id="testCustom" name="this is a test custom tag" />  
</beans>  

import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
  
public class Main {  
  
    public static void main(String[] args) {  
        String xml = "classpath:test.xml";  
        ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { xml });  
        System.out.println(context.getBean("testCustom"));  
    }  
}  

上例输出为:
TestBean {name=this is a test custom tag}

 

 

 

 

 

 

 

 

 

 

Spring的自定义标签