4.1自定义标签使用

很多情况下,我们需要为系统提供可配置化的支持,简单的做法可以直接基于Spring的标准bean来配置,但是配置较为复杂或者需要更多丰富控制的时候,会显得笨拙。此时Spring提供了可拓展的支持,拓展Spring自定义标签大致需要一下几个步骤:
  • 创建一个需要拓展的组件
  • 定义一个XSD文件描述组件内容
  • 创建一个文件,实现BeandefinitionParse接口,用来解析XSD文件中的定义和组件定义。
  • 创建一个Handler文件,拓展自NamespaceHandlerSupport,目的是将组件注册到Spring容器中。
  • 编写spring.handlers和spring.schemas文件。
1)创建一个POJO,用来接收配置文件
package userDefinedXml;

/**
 * @version 版权 Copyright(c)
 * @ClassName:
 * @Descripton: 用于Spring自定义标签解析
 * @author: Shing
 * @date: 2020-10-21 15:45
 */
public class User {
    private String id;
    private String userName;
    private String email;
    //省略get、set
}

 

2)定义一个XSD文件描述组件内容
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.shing.com/schema/user"
        xmlns:tns="http://www.shing.com/schema/user"
        elementFormDefault="qualified">

    <element name="user">
        <complexType>
            <attribute name="id" type="string" />
            <attribute name="userName" type="string" />
            <attribute name="email" type="string" />
        </complexType>
    </element>

</schema>
targetnamespace、element、id、userName、email只要用于验证Spring配置文件中自定义格式。
 
3)创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义
package userDefinedXml;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

/**
 * @version 版权 Copyright(c)
 * @ClassName:
 * @Descripton: 解析XSD文件中的定义和组件定义
 * @author: Shing
 * @date: 2020-10-21 15:54
 */
public class UserBeanDefinitionParse extends AbstractSingleBeanDefinitionParser {
    //Element对应的类
    @Override
    protected Class<?> getBeanClass(Element element) {
        return User.class;
    }

    //从element中解析并提取对应的元素
    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String userName = element.getAttribute("userName");
        String email = element.getAttribute("email");

        if(StringUtils.hasText(userName)){
            builder.addPropertyValue("userName",userName);
        }
        if(StringUtils.hasText(email)){
            builder.addPropertyValue("email",email);
        }
    }
}

 

4)创建一个Handler文件,拓展自NamespaceHandlerSupport,目的是将组件注册到Spring容器中。
package userDefinedXml;

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

/**
 * @version 版权 Copyright(c)
 * @ClassName:
 * @Descripton: 将组件注册到Spring容器
 * @author: Shing
 * @date: 2020-10-21 16:04
 */
public class MyNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("user",new UserBeanDefinitionParse());
    }
}
以上代码很简单,无非是遇到自定义标签<user:aaa这样类似user开头的元素,将会把这个元素扔给对应的UserBeanDefinitionParser去解析。
 
5)编写spring.handlers和spring.schemas文件,默认在工程的/META-INF文件夹下
spring.handlers
http\://www.shing.com/schema/user=userDefinedXml.MyNamespaceHandler
spring.schemas
http\://www.shing.com/schema/user.xsd=META-INF/userDefined.xsd

到了这里,自定义配置就结束来,Spring加载到自定义标签后就会去spring.handlers,spring.schemas找对应的handler和XSD,进而找到对应的handler以及解析元素Parser,从而完成整个自定义元素的解析。spring中默认配置与自定义的区别是自定义的将解析过程交给了用户实现。

6)创建测试的配置文件,在配置文件中引入对应的命名空间以及XSD后,就可以使用自定义标签了。
customDefinition.xml
<?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:myname="http://www.shing.com/schema/user"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.shing.com/schema/user http://www.shing.com/schema/user.xsd">

    <myname:user id="user" userName="aaa" email="bbb" />

</beans>
package userDefinedXml;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @version 版权 Copyright(c)
 * @ClassName:
 * @Descripton:
 * @author: Shing
 * @date: 2020-10-21 16:23
 */
public class customDefinitionXml {

    public static void main(String[] args) {
        ApplicationContext bf = new ClassPathXmlApplicationContext("customDefinition.xml");
        User user = (User) bf.getBean("user");
        System.out.println(user.getUserName()+"--"+user.getEmail());
    }

}

 





posted @ 2021-01-13 17:06  _Shing  阅读(206)  评论(0)    收藏  举报