在Spring-Framework
下新建Module
工程结构

依赖
spring-test-fy.gradle
需要添加spring-context
的依赖
可参考 spring-test.gradle

代码
Teacher
| package com.fy.test.model; |
| |
| public class Teacher { |
| private Student student; |
| |
| public Teacher(Student student) { |
| this.student = student; |
| } |
| |
| public Student getStudent() { |
| return student; |
| } |
| |
| public void setStudent(Student student) { |
| this.student = student; |
| } |
| |
| @Override |
| public String toString() { |
| return "Teacher{" + |
| "Student=" + student + |
| '}'; |
| } |
| } |
| |
| |
Student
| package com.fy.test.model; |
| |
| public class Student { |
| private String name; |
| private Integer age; |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public Integer getAge() { |
| return age; |
| } |
| |
| public void setAge(Integer age) { |
| this.age = age; |
| } |
| |
| @Override |
| public String toString() { |
| return "Student{" + |
| "name='" + name + '\'' + |
| ", age=" + age + |
| '}'; |
| } |
| } |
| |
开始自定义
先定义自己的标签fy.xsd
说明:http://fy.custom.com/schema/fy
自定义的,可以随便命名,但是要保持前后统一哦
可以参考org/springframework/beans/factory/xml/spring-beans.xsd
| <?xml version="1.0" encoding="UTF-8"?> |
| <xsd:schema xmlns="http://fy.custom.com/schema/fy" |
| xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
| targetNamespace="http://fy.custom.com/schema/fy" |
| elementFormDefault="qualified" |
| attributeFormDefault="unqualified"> |
| <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/> |
| |
| <xsd:element name="bean"> |
| <xsd:complexType> |
| <xsd:complexContent> |
| |
| <xsd:extension base="identifiedType"> |
| |
| <xsd:group ref="beanElements"/> |
| |
| <xsd:attributeGroup ref="beanAttributes"/> |
| </xsd:extension> |
| </xsd:complexContent> |
| </xsd:complexType> |
| </xsd:element> |
| |
| <xsd:attributeGroup name="beanAttributes"> |
| <xsd:attribute name="name" type="xsd:string"> |
| <xsd:annotation> |
| <xsd:documentation><![CDATA[ |
| Can be used to create one or more aliases illegal in an (XML) id. |
| Multiple aliases can be separated by any number of spaces, commas, |
| or semi-colons (or indeed any mixture of the three). |
| ]]></xsd:documentation> |
| </xsd:annotation> |
| </xsd:attribute> |
| <xsd:attribute name="class" type="xsd:string"> |
| <xsd:annotation> |
| <xsd:documentation source="java:java.lang.Class"><![CDATA[ |
| The fully qualified name of the bean's class, except if it serves only |
| as a parent definition for child bean definitions. |
| ]]></xsd:documentation> |
| </xsd:annotation> |
| </xsd:attribute> |
| <xsd:anyAttribute namespace="##other" processContents="lax"/> |
| </xsd:attributeGroup> |
| |
| <xsd:complexType name="identifiedType" abstract="true"> |
| <xsd:annotation> |
| <xsd:documentation><![CDATA[ |
| The unique identifier for a bean. The scope of the identifier |
| is the enclosing bean factory. |
| ]]></xsd:documentation> |
| </xsd:annotation> |
| <xsd:attribute name="id" type="xsd:string"> |
| <xsd:annotation> |
| <xsd:documentation><![CDATA[ |
| The unique identifier for a bean. A bean id may not be used more than once |
| within the same <beans> element. |
| ]]></xsd:documentation> |
| </xsd:annotation> |
| </xsd:attribute> |
| </xsd:complexType> |
| |
| <xsd:group name="beanElements"> |
| <xsd:sequence> |
| <xsd:choice minOccurs="0" maxOccurs="unbounded"> |
| <xsd:element ref="property"/> |
| <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/> |
| </xsd:choice> |
| </xsd:sequence> |
| </xsd:group> |
| |
| <xsd:element name="property"> |
| <xsd:complexType> |
| <xsd:attribute name="name" type="xsd:string"/> |
| <xsd:attribute name="value" type="xsd:string"/> |
| </xsd:complexType> |
| </xsd:element> |
| </xsd:schema> |
| |
实现自定义的解析处理类,解析自己定义的标签
自定义标签解析类,通过继承AbstractSingleBeanDefinitionParser
的方式
| package com.fy.test.handler; |
| |
| import org.springframework.beans.factory.support.BeanDefinitionBuilder; |
| import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; |
| import org.springframework.beans.factory.xml.ParserContext; |
| import org.w3c.dom.Element; |
| |
| public class FYCustomBeanParser extends AbstractSingleBeanDefinitionParser { |
| public static final String CLASS_ATTRIBUTE = "class"; |
| |
| @Override |
| protected String getBeanClassName(Element element) { |
| if (element.hasAttribute(CLASS_ATTRIBUTE)){ |
| return element.getAttribute(CLASS_ATTRIBUTE); |
| } |
| return null; |
| } |
| |
| @Override |
| protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { |
| |
| parserContext.getDelegate().parsePropertyElements(element, builder.getBeanDefinition()); |
| } |
| } |
| |
自定义标签解析处理类,用来指定自定义标签的用哪个解析类来解析,通过继承NamespaceHandlerSupport
的方式
| package com.fy.test.handler; |
| |
| import org.springframework.beans.factory.xml.NamespaceHandlerSupport; |
| |
| public class FYCustomBeanHandler extends NamespaceHandlerSupport { |
| |
| @Override |
| public void init() { |
| |
| registerBeanDefinitionParser("bean", new FYCustomBeanParser()); |
| } |
| } |
| |
spring.handlers
| http\://fy.custom.com/schema/fy=com.fy.test.handler.FYCustomBeanHandler |
spring.schemas
| http\://fy.custom.com/schema/fy.xsd=config/fy.xsd |
使用自定义标签fy-beans.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:fy="http://fy.custom.com/schema/fy" |
| xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd |
| http://fy.custom.com/schema/fy http://fy.custom.com/schema/fy.xsd"> |
| |
| <bean id="teacher" class="com.fy.test.model.Teacher"> |
| <property name="student" ref="student"/> |
| </bean> |
| <bean id="student" class="com.fy.test.model.Student"> |
| <property name="name" value="张三"/> |
| <property name="age" value="18"/> |
| </bean> |
| |
| <fy:bean id="student" class="com.fy.test.model.Student"> |
| <fy:property name="name" value="李四"/> |
| <fy:property name="age" value="20"/> |
| </fy:bean> |
| </beans> |
| |
测试
| package com.fy.test; |
| |
| import com.fy.test.model.Student; |
| import org.junit.jupiter.api.Test; |
| import org.springframework.context.ApplicationContext; |
| import org.springframework.context.support.ClassPathXmlApplicationContext; |
| |
| |
| public class FYCustomTest { |
| private final static String FY_BEANS_XML = "fy-beans.xml"; |
| |
| @Test |
| public void testGetBean() { |
| ApplicationContext context = new ClassPathXmlApplicationContext(FY_BEANS_XML); |
| Student student = context.getBean("student", Student.class); |
| System.out.println(student); |
| } |
| } |
| |
结果OK

遇到的问题
我是在Spring源码5.2.x版本中测试的,一直报这个错,始终编译不过

解决办法
把gradle
下的docs.gradle
文件中第220
行的校验注释掉,就可以了

自定义标签解析的原理


重点在这个resolve(String namespaceUri)
方法里


| protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { |
| this.parsers.put(elementName, parser); |
| } |
在解析的时候
| public BeanDefinition parse(Element element, ParserContext parserContext) { |
| BeanDefinitionParser parser = findParserForElement(element, parserContext); |
| return (parser != null ? parser.parse(element, parserContext) : null); |
| } |
| private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { |
| String localName = parserContext.getDelegate().getLocalName(element); |
| BeanDefinitionParser parser = this.parsers.get(localName); |
| if (parser == null) { |
| parserContext.getReaderContext().fatal( |
| "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); |
| } |
| return parser; |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律