自己构建一个Spring自定义标签以及原理讲解

平时不论是在Spring配置文件中引入其他中间件(比如dubbo),还是使用切面时,都会用到自定义标签。那么配置文件中的自定义标签是如何发挥作用的,或者说程序是如何通过你添加的自定义标签实现相应的功能的呢?且看下文。

通过对本文的阅读,你会在阅读涉及到自定义标签的源码功能时事半功倍,而且还可以自己动手做出一个自己的自定义标签。

先呈上我自己在本地实现自定义标签的代码及对应讲解:

1、先无脑输出一个测试要用到的Bean类

 1 public class User {
 2
 3     private String userName;
 4     private String emailAddress;
 5
 6     public String getUserName() {
 7         return userName;
 8     }
 9
10     public void setUserName(String userName) {
11         this.userName = userName;
12     }
13
14     public String getEmailAddress() {
15         return emailAddress;
16     }
17
18     public void setEmailAddress(String emailAddress) {
19         this.emailAddress = emailAddress;
20     }
21 }

2、spring的xml配置文件,以及在配置文件中引入自定义标签跟它的命名空间

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xmlns:aop="http://www.springframework.org/schema/aop"
 6        xmlns:mvc="http://www.springframework.org/schema/mvc"
 7        xmlns:myname="http://www.zzq.com/schema/user"
 8        xsi:schemaLocation="http://www.springframework.org/schema/beans
 9       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
10       http://www.springframework.org/schema/context
11       http://www.springframework.org/schema/context/spring-context-4.0.xsd
12       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
13       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
14       http://www.zzq.com/schema/user http://www.zzq.com/schema/user.xsd">
15
16     <aop:aspectj-autoproxy proxy-target-class="true"/>
17     <mvc:annotation-driven/>
18     <context:component-scan base-package="myDemoHome"/>
19     <context:property-placeholder location="classpath:properties/config.properties" ignore-unresolvable="true"/>
20
21     <myname:myPw id="testUserBean" userName="zzq" emailAddress="[email protected]"/>
22
23 </beans>

3、从2中可以看到,命名空间中我添加了自定义的xmlns:myname="http://www.zzq.com/schema/user",以及http://www.zzq.com/schema/user跟http://www.zzq.com/schema/user.xsd。

其中紧跟xmlns冒号后面的部分,就是我们自定义标签引号前的部分,比如此处定义了myname,那么自定义标签中我就可以<myname:XXX/>这样引用了,其中的XXX则是在命名空间中定义的myPw。

中间http://www.zzq.com/schema/user对应此自定义标签的handler,放在Spring.handlers中。

最后的http://www.zzq.com/schema/user.xsd则定义了此自定义标签的XXX,即自定义标签冒号后面有什么,由此xsd定义,放在Spring.schemas中。

Spring.handlers跟Spring.schemas文件都放在META-INF目录下,因为spring会默认去此目录下读。

Spring.handlers如下所示:

http\://www.zzq.com/schema/user=myDemoHome.springElement.bdParser.UserNamespaceHandler

Spring.schemas如下所示:

http\://www.zzq.com/schema/user.xsd=META-INF/spring-test.xsd

3.1  自定义标签的解析类UserNamespaceHandler构建

 1 package myDemoHome.springElement.bdParser;
 2
 3 import myDemoHome.springElement.User;
 4 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 5 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
 6 import org.springframework.util.StringUtils;
 7 import org.w3c.dom.Element;
 8
 9 public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
10
11     @Override
12     protected Class getBeanClass(Element element) {
13         return User.class;
14     }
15
16     @Override
17     protected void doParse(Element element, BeanDefinitionBuilder builder) {
18         String name = element.getAttribute("userName");
19         String address = element.getAttribute("emailAddress");
20
21         if (StringUtils.hasText(name)) {
22             builder.addPropertyValue("userName", name);
23         }
24         if (StringUtils.hasText(address)) {
25             builder.addPropertyValue("emailAddress", address);
26         }
27     }
28
29 }

就是对element中的标签进行解析处理,完成从xml中的标签属性向对象值的转化

3.2 自定义标签解析类的注册 UserNamespaceHandler

 1 package myDemoHome.springElement.bdParser;
 2
 3 import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
 4
 5 public class UserNamespaceHandler extends NamespaceHandlerSupport {
 6     @Override
 7     public void init() {
 8         registerBeanDefinitionParser("myPw", new UserBeanDefinitionParser());
 9     }
10 }

此处的意思就是当遇到myPw这个标签的时候,往spring容器中注入这个标签的解析类,以完成后续对标签属性的解析。看到此处,各位道友有没有想起AOP的自定义注解aspectj-autoproxy 的解析呢?其实套路都是一样的。

3.3 xsd文件spring-test.xsd的定义

<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.zzq.com/schema/user"
        elementFormDefault="qualified">

    <element name="myPw">
        <complexType>
            <attribute name="id" type="string"/>
            <attribute name="userName" type="string"/>
            <attribute name="emailAddress" type="string"/>
        </complexType>
    </element>
</schema>

此文件规定了自定义注解的标签,以及对应的属性

4、测试类ElementTest

 1 package myDemoHome.springElement;
 2
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5
 6 public class ElementTest {
 7     public static void main(String[] args) {
 8         ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath*:spring/spring-config.xml");
 9         User user = (User)applicationContext.getBean("testUserBean");
10         System.out.println(user.getEmailAddress());
11     }
12 }

再附上一张所用类的位置关系图

至此大功告成,最后运行一下测试类:

功德圆满!

总结:

构建一个自定义标签的流程便是如此,相信如果后面再遇到自定义标签,按照此构建思路反向解析一下便也能顺藤摸瓜知晓它的来龙去脉。其实看一下之前我们用过的中间件,像dubbo,也是一样的套路,只是功能更繁杂。

dubbo的jar包如图所示:

也是用了这三个实现的标签引用。

写在最后:至此,19年金三银四找工作之途的总结(包括技术跟个人感悟,感兴趣的道友可以移步我的另几篇博文一探究竟)便告一段落。今年自从去年下半年的资本收缩后,行情确实相较以往差了一些(虽然贫道也才17年入行),但我个人的感觉

是行业整体回归理性,之前是经过三四个月培训班下来就月薪十几K而且都抢着招人,太不正常。话说回来,不管外界行情怎样,只要你喜欢做这一行,都要静下心来多学习多探究,才能在不断的积累中让自己更上一层。今年年初两次阿里的面试

经历也让自己对于自身能力有了更客观真实的认识,不管是从项目经历还是个人技术积累上,都差很多。目前贫道新公司所处的部门,对技术比较注重,且技术大佬不少,工作都很认真,正是"发粪涂墙"之际,内心充满激情。后面的博文目前打算

更多偏向微服务(因为目前公司的项目用的就是微服务架构)、并发编程(因为前段时间买了本并发编程实战)。技术积累不是一朝一夕,与各位道友共勉!

原文地址:https://www.cnblogs.com/zzq6032010/p/10657907.html

时间: 2024-10-20 01:26:41

自己构建一个Spring自定义标签以及原理讲解的相关文章

(转载)Spring自定义标签的原理

Spring自定义标签的原理 XML通常通过DTD.XSD定义,但DTD的表达能力较弱,XSD定义则能力比较强,能够定义类型,出现次数等.自定义标签需要XSD支持,在实现时使用Namespace扩展来支持自定义标签. <bean id="beanId" class="com.xxx.xxxx.Xxxxx"> <property name="property1"> <value>XXXX</value>

利用反射模拟一个spring的内部工作原理

这个简单的案例是实行了登录和注册的功能,没有链接数据库. 在bean中id 是唯一的,id和name的区别在于id不能用特殊字符而name可以用特殊字符,比如:/-\.... 1 package com.obtk.reflect; 2 3 public class Logon { 4 /** 5 * 帐号密码长度大于六位字符就成功,否则失败! 6 * */ 7 public String select(String name, String pass) { 8 if (name.length()

spring 自定义标签 学习

自定义配置文件到spring 中,有时候想做一些数据结构的配置化信息,根据业务做一个扩展. 首先: 在项目的META-INF目录下新建两个文件spring.handlers,和spring.shcemas Spring.handlers在类org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver中已经写死了要取mapping的handlerMappingsLocation的路径 public static fina

Spring 自定义标签

Spring 工作流程是先加载解析xml配置文件:配置文件中存在默认的标签,也可以自定义标签.解析默认标签调用: 1 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { 2 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { 3 importBeanDefinitionResource(ele); 4 } 5 else if

Spring 自定义标签配置

前景:经常使用一些依赖于Spring的组件时,发现可以通过自定义配置Spring的标签来实现插件的注入,例如数据库源的配置,Mybatis的配置等.那么这些Spring标签是如何自定义配置的?学习Spring标签的自定义配置为以后实现分布式服务框架做技术储备. 技术分析:Spring的标签配置是通过XML来实现的,通过XSD(xml Schema Definition)来定义元素,属性,数据类型等. Spring自定义标签解析 1.Spring启动时通过扫描根目录下的META-INF文件下的sp

spring 自定义标签 学习二

在上篇中写的只支持写属性,不支持标签property的写法,但是如果有时候我们还想做成支持 property的用法,则可以在xsd中增加spring 自带的xsd引用 修改xsd文件如下: <?xml version="1.0"encoding="UTF-8"?> <xsd:schema xmlns="http://www.ruishenh.com/custom/myTest" xmlns:xsd="http://ww

快速构建一个Spring Boot+MyBatis的项目IDEA(附源码下载)

如何快速构建一个Spring Boot的项目 工具 idea JDK版本 1.8 Spring Boot 版本 1.5.9 环境搭建实现:最基础前端可以访问到数据库内的内容 开始 IDEA 内部新建一个项目,项目类型选择Spring Initializr,Project SDK选择适合你当前环境的版本,这里我选择的是1.8(Spring Boot 2.0以上的版本,JDK选择请选择1.8即以上版本),构建服务选择默认就好,点击Next 填写Group和Artifact(此处我使用的是默认,请根据

Spring自定义标签

一.原理: 1.Spring通过XML解析程序将其解析为DOM树, 2.通过NamespaceHandler指定对应的Namespace的BeanDefinitionParser将其转换成BeanDefinition. 3.再通过Spring自身的功能对BeanDefinition实例化对象. 二.自定义标签步骤 1.定义三个文件 META-INF/spring.handlers http\://www.newlandframework.com/dubbo=com.newlandframewor

dubbo源码学习(二) : spring 自定义标签

做dubbo的配置时很容易发现,dubbo有一套自己的标签,提供给开发者配置,其实每一个标签对应着一个 实体,在容器启动的时候,dubbo会对所有的配置进行解析然后将解析后的内容设置到实体里,最终dubbo会根据实体中的值生成贯穿全局的统一URL.利用自定义标签使配置简单明了化,与spring完美融合.下面自己写一个自定义标签,主要需要如下 几个步骤: 1.编写实体类2.编写Parser解析类3.编写NameSpaceHandle类4.配置spring.handlers5.配置spring.sc