【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)

前言(放在开头的废话)

不知道你有没有注意过命名空间这个东西,或者你有没有注意过xmlns、xmlns:context、xmlns:xsi(更多瞅下图)...

问题来了,这些是啥么?

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第1张图片

​这些是Spring中的命名空间,其主要作用是避免命名冲突,打个比方就是你和张三都有一个叫做heheda的bean,但是由于你们用的是各自的命名空间,就会给你俩的heheda前分别加上表示你俩命名空间的前缀,以免混淆。

Spring中主要分两位两种命名空间:默认命名空间和自定义命名空间(函数parseBeanDefinitions()中)

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第2张图片

​Spring中的默认命名空间有以下四个(其余都算自定义)

  • public static final String NESTED_BEANS_ELEMENT = "beans";

  • public static final String ALIAS_ELEMENT = "alias";

  • public static final String NAME_ATTRIBUTE = "name";

  • public static final String ALIAS_ATTRIBUTE = "alias";

如何实现自定义标签

那么如何实现一个自定义标签,并实现解析~~开始搞起(奋斗脸.gif)!

1. 新建一个实体类AqinEntity

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第3张图片

AqinEntity.java

package com.aqin;

/**
 * @author aqin1012 AQin.
 * @date 2022/4/24 5:45 PM
 * @Version 1.0
 */
public class AqinEntity {
   String id;
   String name;
   String address;

   public String getId() {
      return id;
   }

   public void setId(String id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getAddress() {
      return address;
   }

   public void setAddress(String address) {
      this.address = address;
   }
}

2. 创建实体解析类AqinBeanDefinitionParser

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第4张图片

AqinBeanDefinitionParser.java

package com.aqin;

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

/**
 * @Description
 * @Author aqin1012 AQin.
 * @Date 2022/5/12 3:27 PM
 * @Version 1.0
 */
public class AqinBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

   @Override
   protected Class getBeanClass(Element element) {
      return AqinEntity.class;
   }

   /**
    * 此处缺少某个属性并不会导致程序报错,但是该属性会为null
    * 
    * @param element the XML element being parsed
    * @param builder used to define the {@code BeanDefinition}
    */
   @Override
   protected void doParse(Element element, BeanDefinitionBuilder builder) {
      String id = element.getAttribute("id");
      String name = element.getAttribute("name");
      String address = element.getAttribute("address");

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

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

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


3. 新建自定义命名空间处理类AqinNamespaceHandler

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第5张图片

AqinNamespaceHandler.java

package com.aqin;

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

/**
 * @author aqin1012
 */
public class AqinNamespaceHandler extends NamespaceHandlerSupport {

   @Override
   public void init() {
      registerBeanDefinitionParser("aqin", new AqinBeanDefinitionParser());
   }

}

4. 新建配置文件spring.handlers、spring.schemas和.xsd

我们可以参考源码中别的模块来创建:

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第6张图片

​推荐个偷懒的方法可以直接吧,直接把整个META_INF文件夹复制到我们自己新建的模块中的resources中

像这样

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第7张图片

​删掉用不到的文件,就留下面两个就成

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第8张图片

​1. 修改文件spring.handlers的内容

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第9张图片

​http\://www.aqin.com/schema/aqin=com.aqin.AqinNamespaceHandler

2. 仿照spring-bean.xsd来构造aqin.xsd

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第10张图片

​aqin.xsd




   
      
         
         
         
      
   

3. 修改文件spring.schemas的内容:

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第11张图片

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第12张图片

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第13张图片

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

5. 修改配置文件applicationContext.xml

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第14张图片

applicationContext.xml





   


6. 相关报错处理

Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1

报错详情

​解决方法

这类错误一般是由于标签名不一致导致的

请检查以下几个地方

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第15张图片

​一般情况下,红色圈住文件内的红色部分要保持一致,黄色圈住的文件内的黄色部分要保持一致,嗯嗯啰嗦的俺...

FAILURE: Build failed with an exception.Where:Script '.../gradle/docs.gradle' line: 228

报错详情

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第16张图片

解决方法(这里提供两种)

法1⃣️:注释判断大小写的代码

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第17张图片

​法2⃣️:首字母改成大写

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第18张图片

7. 执行

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第19张图片

如上图就是自定义标签添加成功喽~~~

也可在中途的打断点查看映射关系是否加载成功(如下图)

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第20张图片

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)_第21张图片

又完成一篇~赞~嘻嘻、给自己撒个花~~

你可能感兴趣的:(Java,spring,java,自定义标签,xmlns,schema)