九零后大叔
技术人的点点滴滴

beanfactory篇-(十四)自定义标签是如何奏效的

回顾:通过前面一个章节的了解,我们大概清楚的了解了spring默认标签的解析过程。那么本章节和后面一个章节,我将来细致的看看自定义标签如何使用以及自定义标签是如何成功的被解析的。


一、自定义标签的基础知识

1.spring的默认标签与自定义标签
[1] 常用的默认标签和使用如下:

<import resource="applicationContext-dao.xml"/>

<alias name="sqlSessionFactory" alias="sqlSessionFactory1"/>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- 配置数据源 -->
    <property name="dataSource" ref="dataSourceMaster"/>
    <!-- 加载mybatis的配置文件 -->
    <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/>
    <!-- 自动扫描mapping.xml文件,**表示迭代查找 -->
    <property name="mapperLocations" value="classpath*:com/minesoft/tutorial/mapper/**/*.xml" />
</bean>

[2] 常用的自定义标签和使用如下:

<!-- 配置注解扫描 -->
<context:component-scan base-package="com.minesoft.tutorial,com.minesoft.tutorial.controller">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

<!-- 属性文件配置 -->
<context:property-placeholder location="classpath*:properties/*.properties" ignore-unresolvable="true" order="2"/>

<!-- 事物处理 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager" order="2"/>

<!-- 配置切面处理 -->
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>

<!--配置静态资源访问路径-->
<mvc:resources location="/WEB-INF/js/" mapping="/js/**"/>
<mvc:resources location="/WEB-INF/css/" mapping="/css/**"/>

2.自定义标签的相关概念

[1] 标签命名空间和标签格式校验文件介绍。首先我们先看看applicationContext.xml文件头信息:

   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc" 
   xmlns:aop="http://www.springframework.org/schema/aop"

   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
   http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

每一个自定义标签都归属到一个命名空间名下,而applicationContext.xml文件的头部的这些信息就是该文件内部所有使用自定标签所对应的命名空间。很类似于我们在使用某个java类的时候,我们需要在文件的头部import这个我们需要使用的java类的全限定名;同样的道理,我们想要使用某个自定义标签的时候,我们也需要在文件的头部引入这个自定义标签的命名空间。

不同于java的地方在于,除了引入这个命名空间之外,我们还需要多一步操作,就是指定一个自定义标签格式校验文件,也就是xsd文件。也就是在xsi:schemaLocation=后面添加自己所使用的自定义标签的格式校验文件。上述的例子中,我们看到了有spring-beans.xsd、spring-context.xsd、spring-mvc.xsd、spring-aop.xsd等等的标签格式校验文件,spring-context.xsd用于校验context标签,spring-mvc.xsd用于校验mvc标签,spring-aop.xsd用于校验aop标签。如果我们想要创建一个属于我们自己的自定义标签,那么我们也一定要创建一个xsd文件。

[2] spring.handlers和spring.schemas文件
我们在翻看其它的jar包的时候,经常发现别人的jar包里面经常会有两个文件,那么这两个文件是做什么的呢?二者都可以理解为一个Map信息文件,里面存储的信息都是键值对。所不同的是:
spring.handlers文件的键值对是哪个自定义标签由哪个业务类进行解析。
spring.schemas文件的键值对是哪个自定义标签由哪个路径下的xsd文件校验该标签是否合法。

[3] 到此为止我们知道,我们要创建一个属于自己的自定义标签,有三步必不可少(无先后顺序关系)。
第一步:我们要创建一个自定义标签合法性校验文件
第二步:我们要创建一个自定义标签与该标签解析类的绑定关系文件
第三步:我们要创建一个自定义标签解析类文件


二、如何创建一个自定义标签并使用

1.创建一个jar包工程如下(不含任何文件):

2.创建需要扩展的组件,创建一个Custom类文件。

@Data
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class Custom {

    private Long id;
    private String name;
    private String mobile;
    private String bankcard;
    private String identity;

}

3.在resources文件夹的META-INF目录下,定义XSD文件描述组件内容

<xsd:schema xmlns="http://www.minesoft.com/schema/minesoft"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            elementFormDefault="qualified"
            targetNamespace="http://www.minesoft.com/schema/minesoft">

    <xsd:element name="minesoft">
        <xsd:complexType>
            <xsd:attribute name="id" type="xsd:long"/>
            <xsd:attribute name="name" type="xsd:string"/>
            <xsd:attribute name="mobile" type="xsd:string"/>
            <xsd:attribute name="bankcard" type="xsd:string"/>
            <xsd:attribute name="identity" type="xsd:string"/>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>

4.创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义

public class MinesoftBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    @Override
    protected Class<?> getBeanClass(Element element) {
        return Custom.class;
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {

        Long id = Long.valueOf(element.getAttribute("id"));
        String name = element.getAttribute("name");
        String mobile = element.getAttribute("mobile");
        String bankcard = element.getAttribute("bankcard");
        String identity = element.getAttribute("identity");

        if (id != null) {
            builder.addPropertyValue("id", id);
        }

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

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

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

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

5.创建Handler文件,扩展至NamespaceHandlerSupport,目的是将组件注册到Spring容器

public class MinesoftNamespaceHandler extends NamespaceHandlerSupport {

    public void init() {
        registerBeanDefinitionParser("minesoft", new MinesoftBeanDefinitionParser());
    }
}

6.编写spring.handlers和spring.schemas文件
spring.handlers文件内容如下

http\://www.minesoft.com/schema/minesoft=com.minesoft.custom.schema.MinesoftNamespaceHandler

spring.schemas文件内容如下

http\://www.minesoft.com/schema/minesoft/minesoft.xsd=/META-INF/minesoft.xsd

将上面的六个步骤弄完之后,我们在命令行或者在idea左侧工具栏使用install功能,将当前的工程打成jar包部署到本地仓库。

7.开始测试

首先我们新创建一个测试工程,并在该测试工程的applicationContext.xml文件中添加下面的自定义标签(另外记得在新测试工程pom文件里面依赖前面打的jar包)。

<minesoft:minesoft id="1000" name="sam" mobile="16878765436" identity="4305229387366524X" bankcard="7265382763772"/>

其次我们在测试工程的单元测试类执行如下代码:

ClassPathXmlApplicationContext cac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
Custom custom = cac.getBean(Custom.class);
System.out.println(JSONObject.toJSONString(custom));
cac.close();

执行上面的代码,我们会发现,我们在applicationContext.xml中使用的自定义标签被spring成功的解析生效了。该标签被解析成了一个Custom业务bean对象,该自定义标签的使用和bean默认标签的使用非常类似。

更多知识请关注公众号

赞(0) 赏一下
未经允许不得转载:九零后大叔的技术博客 » beanfactory篇-(十四)自定义标签是如何奏效的
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

九零后大叔的技术博客

联系我们联系我们

感谢您的支持

支付宝扫一扫打赏

微信扫一扫打赏