共计 5456 个字符,预计需要花费 14 分钟才能阅读完成。
引言
自从 SpringBoot
时代的到来,去除了 Spring
的各种繁琐的 XML
配置, 让咱们能够腾出双手以便于更加专一的搬砖。
记得那时候刚学 Spring
的时候,每天被 Spring
的各种 XMl
配置文件折磨的不行,每引入一个新的框架,最放心的就是 jar
抵触、哪个配置文件又配的不对、配置文件没有起作用。所以每次搭建好一个我的项目就把配置文件用小笔记记录下来,
不便下次在整合我的项目的时候间接 copy 复制就好。上面咱们就以 Spring
整合 dubbo
的事例看下
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="demo-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20890"/>
<bean id="demoService" class="org.apache.dubbo.samples.basic.impl.DemoServiceImpl"/>
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService" ref="demoService"/>
</beans>
上述代码中咱们有看到 dubbo
自定义了一套本人的标签,<dubbo:application> ,<dubbo:registry> ,<dubbo:protocol>,<dubbo:service>
咱们心中是不是有点小疑难:这些标签在 Spring
我的项目启动的时候是如何被 Spring
治理的?是怎么被 Spring
来辨认的?
如果咱们本人轻易定义一个标签 Spring
是否可能辨认?咱们去翻翻 Spring
的官网发现这玩意其实就是 Spring
提供的 XML schema
的扩大反对。只有依照它的步骤来,咱们就能够配置任何咱们自定义的标签。XML schema
扩大机制是什么?这个兴许好多人没听过:
Spring 为基于 XML 构建的利用提供了一种扩大机制,用于定义和配置 Bean。它容许使用者编写自定义的 XML bean 解析器,并将解析器自身以及最终定义的 Bean 集成到 Spring IOC 容器中。
咱们能够看看官网 https://docs.spring.io/spring…
10.2. XML Schema Authoring 这个是次要介绍它的。
如何实现一个自定义 XML 扩大
官网有介绍,要实现一个自定义的XML Schema
总共须要 4 步:
- 编写一个 XML schema 文件形容的你节点元素。
- 编写一个 NamespaceHandler 的实现类
- 编写一个或者多个 BeanDefinitionParser 的实现 (关键步骤).
- 注册上述的 schema 和 handler。
既然只有依照这四步来,那咱们就照着这个文档来本人实现一个。
Authoring the Schema
编写一个javajr.xsd 放入我的项目的 resources/META-INF 文件夹外面(这个也能够是其余路劲)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns="https://www.javajr.cn/schema/javajr"
targetNamespace="https://www.javajr.cn/schema/javajr">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:element name="application">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="website" type="xsd:string" use="required"/>
<xsd:attribute name="weixin" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
targetNamespace="https://www.javajr.cn/schema/javajr"
这里targetNamespace
的地址前面有用到。-
这里咱们就定义了一个元素 application 外面有两个属性别离为
website
和weixin
。编写一个 NamespaceHandler
package org.spring.demo.schema; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; public class MyNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { // 这个名字也不是轻易取的,下面编写 xsd 的根节点元素的 name,<xsd:element name="application"> registerBeanDefinitionParser("application", new MyBeanDefinitionParser()); } }
这个
NamespaceHandler
就是将一个XML
节点解析成IOC
容器中的一个实体类。也就是说相当于在xml
外面的配置的对象,通过Spring ioc
容器治理起来了编写 BeanDefinitionParser 的实现类
package org.spring.demo.schema; import org.spring.demo.domain.JavajrDomain; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; public class MyBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { @Override protected Class<?> getBeanClass(Element element) {return JavajrDomain.class;} @Override protected void doParse(Element element, BeanDefinitionBuilder bean) { // this however is an optional property String website = element.getAttribute("website"); if (StringUtils.hasText(website)) {bean.addPropertyValue("website",website); } String weiXin = element.getAttribute("weixin"); if (StringUtils.hasText(weiXin)) {bean.addPropertyValue("weixin",weiXin); } } }
下面在这个实现类只是简略的做了一个赋值操作,你如果须要有本人的逻辑业务也能够自行来实现。下面还有一个 JavajrDomain 这个实体类就不贴代码,就一个简略的
javabean
外面蕴含了两个属性 weixin 和 website。注册 schema 组件
最初在
resources/META-INF
目录下增加两个配置文件(spring.handler 和 spring.schema
): -
resources/META-INF/spring.handlers
https\://www.javajr.cn/schema/javajr=org.spring.demo.schema.MyNamespaceHandler
-
resources/META-IN/spring.schemas
https\://www.javajr.cn/schema/javajr.xsd=META-INF/javajr.xsd
在这个中央的时候咱们其实能够以版本号来进行命名,不便咱们能够应用多个不同的版本,Spring-beans 就是这么玩的。
测试自定义 schema
- 在
resources
目录下新建一个applicationContext.xml
文件
这个文件就是应用下咱们咱们本人自定义的schema
,这个文件须要留神的就是下面标红的这几行,个别如果咱们有引入过第三方的框架,比方mq
、或者dubbo
等它们都有自定义的这些玩意。 -
编写一个启动类
public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); JavajrDomain bean = ctx.getBean(JavajrDomain.class); System.out.println(bean.toString()); }
咱们能够看到控制台输入
JavajrDomain{weixin='javajr8', website='javajr.cn'}
- 到这里咱们本人实现的一个
XML schema
就实现了,是不是很简略,只有照着官网文档撸就能够了。照着撸的过程可能有几个小细节须要留神下引入XML schema
的时候须要留神下空格,或者一些特殊符号。
上述代码曾经提交到了 gitee 上https://gitee.com/javajr/spring-schema-demo
感兴趣的敌人能够间接下载下来run
下,不过还是不倡议这么玩,最好还是本人入手去尝试下,毕竟也就四步,照着文档来。
Dubbo 中的 XML schema 扩大
在文章开始的时候咱们有介绍 dubbo
自定义的XML schema
,上面咱们一起关上dubbo
源码看看它是如何来实现的,看上面这个截图,也是依照那四步来的。
SpringBoot 的 starter
当初有了 SpringBoot
之后以前用这个 XML schema
配置的框架,大多数都会有对应的 starter
来进行封装,starter
的应用比起 XML schema
的应用还是简略多了,开箱即用,无需编写很多的配置文件。如果不是很分明 SpringBoot
的starter
的举荐去看看这两篇文章《面试高频题:springBoot 主动拆卸的原理你能说进去吗?》《保姆级教程,手把手教你实现一个 SpringBoot 的 starter》。
总结
尽管当初 XML schema
扩大用的不多了,然而应该也还有比拟老的我的项目在应用把,如果还是比拟老的我的项目,须要引入一个什么样的框架,咱们至多须要晓得须要怎么去引入,网上尽管有很多文章能够借鉴,然而咱们也应该知其然知其所以然。而不是间接把配置文件单纯的copy
过去。咱们应该晓得为啥须要 copy
这个 xsd
,为什么没有这个xsd
,idea
不糊辨认会报错。
完结
- 因为本人满腹经纶,难免会有纰漏,如果你发现了谬误的中央,还望留言给我指出来, 我会对其加以修改。
- 如果你感觉文章还不错,你的转发、分享、赞叹、点赞、留言就是对我最大的激励。
- 感谢您的浏览, 非常欢送并感谢您的关注。
伟人的肩膀摘苹果:
https://javajr.cn
https://docs.spring.io/spring…
https://www.cnkirito.moe/spri…