基于Spring 自定义标签实现
程序员文章站
2022-03-06 13:34:51
...
一、源码分析:
Spring标签的定义分为默认标签和自定义标签
Spring源代码:[DefaultBeanDefinitionDocumentReader.java]
Spring其他集成组件如SpringMVC使用了自定义标签。
二、实现自定义标签
步骤:
1、创建一个需要扩展的组件。
如:定义一个User来接受xml文件信息
2、定义一个XSD文件描述主键内容。
如创建了一个user.xsd文件
3、创建一个文件、实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义
4、创建一个handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器中
5、编写spring.handlers和Spring.schemas文件。这两个文件需放在resources/META-INF下
spring.handlers文件:指定NamespaceHander位置
spring.schemas文件:指定xsd文件映射位置
上面已经完成了对自定义标签的实现,那接下来就测试一下咯
spring-user.xml文件定义
Test运行代码:
说明:如想了解具体实现看《Spring源码深度解析》的第4章节
Spring标签的定义分为默认标签和自定义标签
Spring源代码:[DefaultBeanDefinitionDocumentReader.java]
/** * Parse the elements at the root level in the document: * "import", "alias", "bean". * @param root the DOM root element of the document */ protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { //对beans的处理 if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { //对默认标签处理 parseDefaultElement(ele, delegate); } else { //对自定义标签处理 delegate.parseCustomElement(ele); } } } } else { //对自定义标签处理 delegate.parseCustomElement(root); } }
Spring其他集成组件如SpringMVC使用了自定义标签。
二、实现自定义标签
步骤:
1、创建一个需要扩展的组件。
如:定义一个User来接受xml文件信息
package ppfuns; /** * Created with IntelliJ IDEA. * User: ** * Date: 2017/11/22 * Time: 10:09 * To change this template use File | Settings | File Templates. */ public class User { private String username; private String email; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
2、定义一个XSD文件描述主键内容。
如创建了一个user.xsd文件
<?xml version="1.0" encoding="utf-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.lexueba.com/schema/user" xmlns:tns="http://www.lexueba.com/schema/user" elementFormDefault="qualified"> <element name="user"> <complexType> <attribute name="id" type="string"/> <attribute name="userName" type="string"/> <attribute name="email" type="string"/> </complexType> </element> </schema>
3、创建一个文件、实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义
package ppfuns.parser; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import ppfuns.User; /** * Created with IntelliJ IDEA. * User: 简德群 * Date: 2017/11/22 * Time: 10:22 * To change this template use File | Settings | File Templates. */ public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { /** * Element 对应的元素User * @param element * @return */ protected Class getBeanClass(Element element){ return User.class; } /** * 从element元素中提取对应元素的值 * @param element * @param builder */ @Override protected void doParse(Element element, BeanDefinitionBuilder builder) { String username = element.getAttribute("name"); String email = element.getAttribute("email"); if(StringUtils.hasText(username)){ builder.addPropertyValue("name",username); } if(StringUtils.hasText(email)){ builder.addPropertyValue("email",email); } } }
4、创建一个handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器中
package ppfuns.parser; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import ppfuns.User; /** * Created with IntelliJ IDEA. * User: 简德群 * Date: 2017/11/22 * Time: 10:22 * To change this template use File | Settings | File Templates. */ public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { /** * Element 对应的元素User * @param element * @return */ protected Class getBeanClass(Element element){ return User.class; } /** * 从element元素中提取对应元素的值 * @param element * @param builder */ @Override protected void doParse(Element element, BeanDefinitionBuilder builder) { String username = element.getAttribute("name"); String email = element.getAttribute("email"); if(StringUtils.hasText(username)){ builder.addPropertyValue("name",username); } if(StringUtils.hasText(email)){ builder.addPropertyValue("email",email); } } }
5、编写spring.handlers和Spring.schemas文件。这两个文件需放在resources/META-INF下
spring.handlers文件:指定NamespaceHander位置
http\://www.lexueba.com/schema/user=ppfuns.parser.MyNameSpaceHandler
spring.schemas文件:指定xsd文件映射位置
http\://www.lexueba.com/schema/user/user.xsd=user.xsd
上面已经完成了对自定义标签的实现,那接下来就测试一下咯
spring-user.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:myName="http://www.lexueba.com/schema/user" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.lexueba.com/schema/user http://www.lexueba.com/schema/user/user.xsd" > <myName:user id="userBean" userName="jiandequn" email="9780307441@qq.com" ></myName:user> </beans>
Test运行代码:
package ppfuns.junit; import junit.framework.Assert; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import ppfuns.lookup.TestAbstractLookupMethod; import ppfuns.replaceMethod.ReplacedMethodTest; /** * Created with IntelliJ IDEA. * User: 简德群 * Date: 2017/11/27 * Time: 9:56 * To change this template use File | Settings | File Templates. */ public class JunitTest { @Test public void test(){ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("spring-user.xml")); ppfuns.User t1 = (ppfuns.User) bf.getBean("userBean"); Assert.assertSame(t1,t1); System.out.println(t1.getUsername()+","+t1.getEmail()); } }
说明:如想了解具体实现看《Spring源码深度解析》的第4章节
上一篇: 属性文件读取方式
推荐阅读