top
本文目录
一、自定义命名空间和标签
1. 确定相关名称和路径
2. 编写标签约束文件和映射
3. 编写处理器映射文件和处理器
4. 编写标签解析器
二、自定义命名空间的使用

Spring 创建自定义命名空间和自定义标签


共计 3785 个字符,预计需要花费 10 分钟才能阅读完成。

之前有了解过 Spirng 是如何解析第三方 xml 标签的,那么可以根据该原理写一个自定义命名空间和自定义标签,有助于我们学习其他相关框架。

接下来就自定义一个命名空间下的 mybean 标签,往容器中存放 mybean 配置的对象对象。

一、自定义命名空间和标签

通常分为以下几个步骤:

  • 1.确定命名空间名称、schema 虚拟路径、标签名称
  • 2.编写标签约束文件和映射
  • 3.编写处理器映射文件和处理器
  • 4.编写标签解析器

1. 确定相关名称和路径

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:amjun="https://www.qcyqq.com/amjun"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           https://www.qcyqq.com/amjun
                           https://www.qcyqq.com/amjun/amjun-mybean.xsd">

    <amjun:mybean id="userService" class="com.amjun.ioc4.service.impl.UserServiceImpl"/>
</beans>

这里用 xml 里面的配置文件里面的来说明以下,指定命名空间为 https://www.qcyqq.com/amjun,对应的 schema 虚拟路径为 https://www.qcyqq.com/amjun/amjun-mybean.xsd,标签名为

2. 编写标签约束文件和映射

上面指定了 schema 的虚拟路径为 https://www.qcyqq.com/amjun/amjun-mybean.xsd,所以需要在 resource 目录下的 META-INF 文件夹下新建文件 spring.schemas。

这里的目录以及文件名称都是定死的,如果不了解请参考开头说的那篇文章

spring.schemas:

http\://www.qcyqq.com/amjun/amjun-mybean.xsd=com/amjun/ioc4/config/amjun-mybean.xsd

这里指定了约束文件放在 resource 目录下的 com/amjun/ioc4/config/ 下,注意这里是多级目录而不是一级。

amjun-mybean.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="https://www.qcyqq.com/amjun"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="https://www.qcyqq.com/amjun">

    <xs:element name="mybean">
        <xs:complexType>
            <xs:attribute name="id" type="xs:string" use="optional"/>
            <xs:attribute name="class" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

这里定义了 mybean 标签的一些约束,比如可以配置属性 id 和 class, 但是 id 十四可选的,class 是必须的,并且类型都为字符串。

3. 编写处理器映射文件和处理器

同样,这里需要配置 spring.handlers,键为命名空间虚拟路径:https://www.qcyqq.com/amjun

spring.handlers:

http\://www.qcyqq.com/amjun=com.amjun.ioc4.config.AmjunNamespaceHandler

可以看见,这里指定了名称空间的处理器。

AmjunNamespaceHandler:


public class AmjunNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {

        this.registerBeanDefinitionParser("mybean", new MybeanBeanDefinitionParser());
    }
}

自定义的处理器需要继承自 NamespaceHandlerSupport,并在初始化中注册标签解析器。

4. 编写标签解析器

MybeanBeanDefinitionParser.java

public class MybeanBeanDefinitionParser implements BeanDefinitionParser {
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        String beanName = element.getAttribute("id");
        String className = element.getAttribute("class");

        if (beanName.isEmpty()) {
            // 如果 id 属性为空,则使用类名的作为 Bean 名称
            beanName = extractClassName(className);
        }

        // 创建一个通用的 Bean 定义
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClassName(className);

        // 将 Bean 定义注册到 Spring 的 Bean 工厂中
        parserContext.getRegistry().registerBeanDefinition(beanName, beanDefinition);
        return beanDefinition;
    }

    /**
     * 获取类名
     * @param fullyQualifiedClassName
     * @return
     */
    private String extractClassName(String fullyQualifiedClassName) {
        int lastIndex = fullyQualifiedClassName.lastIndexOf('.');
        if (lastIndex != -1 && lastIndex < fullyQualifiedClassName.length() - 1) {
            return fullyQualifiedClassName.substring(lastIndex + 1);
        }
        return fullyQualifiedClassName;
    }
}

标签解析器的作用是,解析每个标签配置的内容。mybean 标签的作用就是注册对象,所以会获取 id 和 class 属性,id 属性作为在容器里面的名称,class 是需要创建的对象。

因为标签中 id 是可选的,这里做了特殊处理的是,id 如果为空,就取类名作为名称。

二、自定义命名空间的使用

使用就比较简单了,只需要如下操作即可。

  • 1.在配置文件中引入命名空间
  • 2.在配置文件中使用自定义的标签
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:amjun="https://www.qcyqq.com/amjun"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           https://www.qcyqq.com/amjun
                           https://www.qcyqq.com/amjun/amjun-mybean.xsd">

    <amjun:mybean id="userService" class="com.amjun.ioc4.service.impl.UserServiceImpl"/>
</beans>

测试文件:

public class ApplicationContextTest {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        System.out.println(applicationContext.getBean("userService", UserServiceImpl.class));
    }
}

创建容器后,可以正常在容器中获取到对象,说明整个过程没问题。

提醒:本文发布于411天前,文中所关联的信息可能已发生改变,请知悉!

Tips:清朝云网络工作室

阅读剩余
THE END
icon
0
icon
分享
icon
二维码
icon
海报
发表评论
评论列表

赶快来坐沙发

晚上好👋, 在属于自己的时间好好放松😌~