【Spring源码系列- IOC】
本文目录
前言(放在开头的废话)
如何实现自定义标签
1. 新建一个实体类AqinEntity
2. 创建实体解析类AqinBeanDefinitionParser
3. 新建自定义命名空间处理类AqinNamespaceHandler
4. 新建配置文件spring.handlers、spring.schemas和.xsd
1. 修改文件spring.handlers的内容
2. 仿照spring-bean.xsd来构造aqin.xsd
3. 修改文件spring.schemas的内容:
5. 修改配置文件applicationContext.xml
6. 相关报错处理
Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1
FAILURE: Build failed with an exception.Where:Script '.../gradle/docs.gradle' line: 228
7. 执行
前言(放在开头的废话)
不知道你有没有注意过命名空间这个东西,或者你有没有注意过xmlns、xmlns:context、xmlns:xsi(更多瞅下图)...
问题来了,这些是啥么?
这些是Spring中的命名空间,其主要作用是避免命名冲突,打个比方就是你和张三都有一个叫做heheda的bean,但是由于你们用的是各自的命名空间,就会给你俩的heheda前分别加上表示你俩命名空间的前缀,以免混淆。
Spring中主要分两位两种命名空间:默认命名空间和自定义命名空间(函数parseBeanDefinitions()中)
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
AqinEntity.java
package com.aqin;/*** @author aqin1012 AQin.* @date /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
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 /5/12 3:27 PM* @Version 1.0*/public class AqinBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {@Overrideprotected Class<?> getBeanClass(Element element) {return AqinEntity.class;}/*** 此处缺少某个属性并不会导致程序报错,但是该属性会为null* * @param element the XML element being parsed* @param builder used to define the {@code BeanDefinition}*/@Overrideprotected 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
AqinNamespaceHandler.java
package com.aqin;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;/*** @author aqin1012*/public class AqinNamespaceHandler extends NamespaceHandlerSupport {@Overridepublic void init() {registerBeanDefinitionParser("aqin", new AqinBeanDefinitionParser());}}
4. 新建配置文件spring.handlers、spring.schemas和.xsd
我们可以参考源码中别的模块来创建:
推荐个偷懒的方法可以直接吧,直接把整个META_INF文件夹复制到我们自己新建的模块中的resources中
像这样
删掉用不到的文件,就留下面两个就成👇
1. 修改文件spring.handlers的内容
http\:///schema/aqin=com.aqin.AqinNamespaceHandler
2. 仿照spring-bean.xsd来构造aqin.xsd
aqin.xsd
<?xml version="1.0" encoding="UTF-8" standalone="no"?><schema xmlns="/2001/XMLSchema"targetNamespace="/schema/aqin"xmlns:tns="/schema/aqin"elementFormDefault="qualified"><element name="aqin"><complexType><attribute name="id" type="string"/><attribute name="name" type="string"/><attribute name="address" type="string"/></complexType></element></schema>
3. 修改文件spring.schemas的内容:
http\:///schema/aqin.xsd=META-INF/aqin.xsd
5. 修改配置文件applicationContext.xml
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:context="/schema/context"xmlns:aqin1012="/schema/aqin"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd/schema/context /schema/context/spring-context.xsd/schema/aqin /schema/aqin.xsd"><aqin1012:aqin id="aqin1012" name="heheda~" address="浙江省杭州市"/></beans>
6. 相关报错处理
Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1
报错详情
解决方法
这类错误一般是由于标签名不一致导致的
请检查以下几个地方
一般情况下,红色圈住文件内的红色部分要保持一致,黄色圈住的文件内的黄色部分要保持一致,嗯嗯啰嗦的俺...
FAILURE: Build failed with an exception.Where:Script '.../gradle/docs.gradle' line: 228
报错详情
解决方法(这里提供两种)
法1⃣️:注释判断大小写的代码
法2⃣️:首字母改成大写
7. 执行
如上图就是自定义标签添加成功喽~~~
也可在中途的打断点查看映射关系是否加载成功(如下图)
又完成一篇~赞~嘻嘻、给自己撒个花🎉~~