spring源码(9)自定义标签与自定义标签的解析

一、自定义标签

  • 建立model
package com.demo3;
/**
 * 
 * @author dqf
 * @since 5.0
 */
public class User {
    private String userName;
    private String email;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
  • 定义一个XSD文件描述
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
targetNamespace="http://www.dqf.com/schema/user"
xmlns:tns="http://www.dqf.com/schema/user" elementFormDefault="qualified">

    <element name="user">
        <complexType>
            <attribute name="id" type="string"></attribute>
            <attribute name="userName" type="string"></attribute>
            <attribute name="email" type="string"></attribute>
        </complexType>
    </element>
</schema>
  • 定义用来解析XSD文件中定义和组件
public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser{

    protected Class getBeanClass(Element element){
        return User.class;
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        String userName = element.getAttribute("userName");
        String email = element.getAttribute("email");
        if(org.springframework.util.StringUtils.hasText(userName)){
            bean.addPropertyValue("userName", userName);
        }
        if(org.springframework.util.StringUtils.hasText(email)){
            bean.addPropertyValue("email", email);
        }
    }
}
  • 定义一个Handler文件,将组件注册到Spring容器
public class MyNamespaceHandler extends NamespaceHandlerSupport{

    @Override
    public void init() {
        registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
    }

}
  • 添加Spring.handlers,spring.schemas文件
http\://www.dqf.com/schema/user=com.demo3.MyNamespaceHandler
http\://www.dqf.com/schema/user.xsd=META-INF/customtag.xsd
  • 测试
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:myname="http://www.dqf.com/schema/user"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.dqf.com/schema/user 
        http://www.dqf.com/schema/user.xsd">

    <myname:user id="testbean" userName="aaa" email="bbb"></myname:user>
    <bean id="myTestBean" class="com.demo.model.MyTestBean" />
</beans>
public class App {
    public static void main(String[] args) {
        BeanFactory bf = new XmlBeanFactory(new ClassPathResource("springContext.xml"));
        MyTestBean testBean = (MyTestBean)bf.getBean("myTestBean");
        System.out.println(testBean.getTestStr());

        User test = (User) bf.getBean("testbean");
        System.out.println(test.getUserName()+","+test.getEmail());
    }
}
  • 结果
    这里写图片描述

二、自定义标签的解析

1、整体过程

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
        //获取对应的命名空间
        String namespaceUri = getNamespaceURI(ele);
        //根据命名空间找到对应的NamespaceHandler
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        }
        //调用NamespaceHandler进行解析
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }

2、提取自定义标签处理器

@Override
    public NamespaceHandler resolve(String namespaceUri) {
        //获取所有已经配置的handler配置
        Map<String, Object> handlerMappings = getHandlerMappings();
        //根据命名空间找到对应的信息
        Object handlerOrClassName = handlerMappings.get(namespaceUri);
        if (handlerOrClassName == null) {
            return null;
        }
        else if (handlerOrClassName instanceof NamespaceHandler) {
            //已经做过解析的,直接从缓存中获取
            return (NamespaceHandler) handlerOrClassName;
        }
        else {
            //没有做过解析的,则返回的是类路径
            String className = (String) handlerOrClassName;
            try {
                //利用反射将类路径转化为类
                Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
                if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                    throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                            "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
                }
                //初始化类
                NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
                //调用自定义的初始化方法
                namespaceHandler.init();
                //记录在缓存中    
                handlerMappings.put(namespaceUri, namespaceHandler);
                return namespaceHandler;
            }
            catch (ClassNotFoundException ex) {
                throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
                        namespaceUri + "] not found", ex);
            }
            catch (LinkageError err) {
                throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
                        namespaceUri + "]: problem with handler class file or dependent class", err);
            }
        }
    }

3、标签解析

@Override
    public final BeanDefinition parse(Element element, ParserContext parserContext) {
        AbstractBeanDefinition definition = parseInternal(element, parserContext);
        if (definition != null && !parserContext.isNested()) {
            try {
                String id = resolveId(element, definition, parserContext);
                if (!StringUtils.hasText(id)) {
                    parserContext.getReaderContext().error(
                            "Id is required for element '" + parserContext.getDelegate().getLocalName(element)
                                    + "' when used as a top-level tag", element);
                }
                String[] aliases = null;
                if (shouldParseNameAsAliases()) {
                    String name = element.getAttribute(NAME_ATTRIBUTE);
                    if (StringUtils.hasLength(name)) {
                        aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
                    }
                }
                BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
                registerBeanDefinition(holder, parserContext.getRegistry());
                if (shouldFireEvents()) {
                    BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
                    postProcessComponentDefinition(componentDefinition);
                    parserContext.registerComponent(componentDefinition);
                }
            }
            catch (BeanDefinitionStoreException ex) {
                parserContext.getReaderContext().error(ex.getMessage(), element);
                return null;
            }
        }
        return definition;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值