[好好面试] 请问Spring如何自定义标签

干货点

了解如何基于spring自定义标签,这是自定义组件的第一步。而最重要的是了解了这个过程后也能够大体了解spring自身部分组件是怎么相互工做和触发的,如spring-aop,组件能够经过反调AopNamespaceHandler了解大体面貌。java

系列文描述

书写该系列文的初衷是由于最近正在负责一个组件的开发,因而打算将接触和学习到的知识写进博客里。这第一篇,记录基于spring如何自定义标签。git

自定义标签的做用

自定义标签能够说是spring为了给相似你我这样的开发人员扩展组件使用的,由于它提供了一个标准的公共可插拔的接口;目前咱们都知道spring很是强大,不过实际上除了spring-core和spring-beans外,其余都是经过自定义标签扩展实现的,其次还有一些开源组件也是,如dubbo等。因此,对于想扩展spring组件的小伙伴来讲,了解如何自定义标签和相应的原理是必须走的第一步。github

那么如何自定义标签

自定义标签能够简单分为四个步骤,分别是spring

  • 编写.schemas文件,通知spring容器咱们定义的xsd文件在哪里;
  • 编写.xsd文件,定义配置时可使用的属性限制或者说支持的那些属性配置;
  • 编写.handlers 文件,扩展NamespaceHandler命名空间注册器和定义及诶喜庆;
  • 在xml文件中使用自定义标签

下面我将以目前开发组件中的代码作例子,从在xml文件中使用开始一步一步逆推,复盘整个自定义标签的过程。网络

首先,先看下目录状况app

resource组件.png

common是我自定义的一个组件组,其中包含的resource组件即是此次使用了自定义标签的主体,能够从截图中看出部分相关文件的存放位置。函数

test-demo.png

test-demo是为了测试此次组件中的自定义标签是否有做用而存在,test-demo只是导入了common组件组而已,再从中调用resource组件。好了,目录结构描述完了,接下来进入正题。学习

看下xml文件如何使用自定义标签测试

applicationContext.xml.png

在第4行这里引入了resource对应的命名空间,spring会从本地扫.handlers,从中找到对应的Key值和Value值,如spa

spring.handlers.png

spring容器会将Key值对应的具体命名空间注册注册入容器,至于这个空间注册器是怎么样的,后面再表,继续描述xml文件。 在以后,咱们能够在xmlns:schemaLocation中找到相似的Key&Value的配置,此次的配置是告诉spring容器从哪里查找XSD文件,这点能够从第六行找到,对应的XSD文件地址是: www.nuofankj.com/resource/re… 细心的话不难发现,这是一个网络地址,是的,确实如此,不过spring的容器倒是先在本地扫.schemas文件,而且读取其中的键值对关系,从中找到本地的文件地址,若是找不到,才会从网络中读取。如spring.schemas文件:

spring.schemas.png

该文件以一种键值对的形式代表了文件在本地的地址,那就是resource.xsd,以后spring容器便会找到resource.xsd文件作校验。如

resource.xsd.png
resource.xsd.png

众所周知,XSD文件的做用是定义配置时可使用的属性限制或者说支持那些属性配置。咱们能够直接看applicationContext.xml中的配置

applicationContext.xml.png

走到这一步就说明配置文件配置好了,接下来即是如何解析的问题了。也就是上文提到com.nuofankj.resource.schema.NamespaceHandler

那么NamespaceHandler类是什么样的

NamespaceHandler.java.png

该类扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器中。其中以SchemaNames.CONFIG_ELEMENT为名注册了一个类ConfigDefinitionParserSchemaNames.CONFIG_ELEMENT对应的变量就是config字符串,目的就是为了解析

config.png

显然,ConfigDefinitionParser就是做为解析器存在的。

接下来看看该解析器是什么样的

ConfigDefinitionParser.png

该解析器继承了AbstractBeanDefinitionParser类,而且重写parseInternal方法,其中的参数element携带resource:config中的全部配置,咱们能够将自身的解析业务放在该函数中。以我自定义的组件为例:

AbstractBeanDefinitionParser.png

我这边的业务是将SchemaNames.PACKAGE_ELEMENT包下的全部类扫出来而且放入list中保存,已经读取出type、suffix等相关配置。

到这一步,自定义标签的过程就所有理清楚了。 相关源码地址:github.com/wiatingpub/…

logo
相关文章
相关标签/搜索