漫谈Spring自定义标签
引言
Java开发的朋友对声明一个Spring Bean肯定不会陌生,日常开发中,除了使用标签声明一个bean外,还经常使用一些自定义的标签,比如spring框架的 ,再如dubbo框架的等等, 这里就为大家介绍下Spring自定义标签的使用及原理。
使用
该部分我们会先从Spring官方介绍的如何创建一个自定义标签、然后再以dubbo框架的dubbo标签为例解读自定义标签的使用。
如何创建一个自定义标签
Spring文档中是这样描述的:
Authoring an XML schema to describe your custom element(s).
Coding a custom NamespaceHandler implementation (this is an easy step, don’t worry).
Coding one or more BeanDefinitionParser implementations (this is where the real work is done).
Registering the above artifacts with Spring (this too is an easy step).
第一步,创建一个xml schema用于约束自定义标签名称、属性、内容等
上方xsd文件定义了一个名称为dateformat, 有两个属性的元素,该元素的默认命名空间为http://www.mycompany.com/schema/myns , xsd文件存放在classpath下,一般都是放在resources/META-INF/目录下
第二步,创建一个NameSpaceHandler
Spring定义Bean可以分为两种,一种是正常的bean, 即,另一种则是自定义标签;对Spring当然知道怎么解析,因为是Spring自己定义的,但对于自定义标签Spring就不知道了,所以需要实现解析程序,Spring解析自定义标签是通过实现一个NameSpaceHandler的接口来完成的
可以看到,自定义NameSpaceHandler只有init方法,并且该方法只是注册了一个Parser
第三步,创建一个Parser,即第二步中注册的Parser(本文中为SimpleDateFormatBeanDefinitionParser),真正的解析标签
第四步,以上三步我们了解了如何定义一个标签、以及如何解析该标签,但似乎漏掉了一个问题,即我们怎么告诉Spring,让Spring碰到`元素时,会执行我们的解析器呢? 这就需要我们把自定义的schema和handler注册到spring,注册方式很简单,即把spring.handlers和spring.schemas放在项目的META-INF目录下,这样spring加载jar包的时候会自动从这些文件中解析到我们的配置,从而在解析到相应标签时使用我们定义的解析类
spring.handlers文件内容:
spring.schemas文件内容:
这里需要说明一点的是,命名空间不一定是要求能访问到的url, 只是用来唯一标识一个标签
依dubbo为例,浅析dubbo自定义标签的实现
dubbo有很多标签,原理都一样,我们这边就举最常用的标签做为说明
这里在dubbo-config模块下的META-INF目录下能看到dubbo.xsd、spring.handlers和spring.schemas文件。
spring.handlers文件内容:
spring.schemas文件内容:
DubboNameSpaceHandler实现:
可以看到dubbo里有很多的标签,且不同的标签在Parser里以不同的入参区分,ReferenceBean核心是getObject()方法,这里主要工作是解析标签并注册到spring bean容器中,感兴趣的朋友可以自行阅读。
原理
这里主要阐述Spring如何调用我们实现的NameSpaceHandler解析自定义标签。如下为spring容器启动大致流程:
详细流程:
DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法我们可以看到,会遍历所有子元素,根据命名空间判断是普通标签还是自定义标签
handlerMappingsLocation:
delegate.parseCustomElement()做的事情主要是,加载META-INF/spring.handlers文件内容,根据元素命名空间找到对应的NameSpaceHandler,此处便是spring.handlers配置的NameSpaceHandler的实现类(即自定义NameSpaceHandler),然后执行parse()方法