<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring面試高頻題如何:自定義XML schema 擴(kuò)展

          共 9639字,需瀏覽 20分鐘

           ·

          2021-06-07 23:40

          ????關(guān)注后回復(fù) “進(jìn)群” ,拉你進(jìn)程序員交流群????
          作者丨阿亮
          來源丨java金融

          引言

          自從SpringBoot時(shí)代的到來,去除了Spring的各種繁瑣的XML配置,讓我們可以騰出雙手以便于更加專注的搬磚。記得那時(shí)候剛學(xué)Spring的時(shí)候,每天被Spring的各種XMl配置文件折磨的不行,每引入一個(gè)新的框架,最擔(dān)心的就是jar沖突、哪個(gè)配置文件又配的不對、配置文件沒有起作用。所以每次搭建好一個(gè)項(xiàng)目就把配置文件用小筆記記錄下來, 方便下次在整合項(xiàng)目的時(shí)候直接copy復(fù)制就好。下面我們就以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自定義了一套自己的標(biāo)簽,dubbo:application ,dubbo:registry ,dubbo:protocol,dubbo:service我們心中是不是有點(diǎn)小疑問:這些標(biāo)簽在Spring項(xiàng)目啟動的時(shí)候是如何被Spring管理的?是怎樣被Spring來識別的?如果我們自己隨便定義一個(gè)標(biāo)簽Spring是否能夠識別?我們?nèi)シ?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Spring的官網(wǎng)發(fā)現(xiàn)這玩意其實(shí)就是Spring提供的 XML schema 的擴(kuò)展支持。只要按照它的步驟來,我們就可以配置任何我們自定義的標(biāo)簽。XML schema 擴(kuò)展機(jī)制是什么?這個(gè)也許好多人沒聽過:

          Spring 為基于 XML 構(gòu)建的應(yīng)用提供了一種擴(kuò)展機(jī)制,用于定義和配置 Bean。它允許使用者編寫自定義的 XML bean 解析器,并將解析器本身以及最終定義的 Bean 集成到 Spring IOC 容器中。

          我們可以看看官網(wǎng)https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#xml-custom 10.2. XML Schema Authoring 這個(gè)是主要介紹它的。

          如何實(shí)現(xiàn)一個(gè)自定義 XML 擴(kuò)展

          官網(wǎng)有介紹,要實(shí)現(xiàn)一個(gè)自定義的XML Schema 總共需要4步:

          • 編寫一個(gè) XML schema 文件描述的你節(jié)點(diǎn)元素。
          • 編寫一個(gè) NamespaceHandler 的實(shí)現(xiàn)類
          • 編寫一個(gè)或者多個(gè) BeanDefinitionParser 的實(shí)現(xiàn) (關(guān)鍵步驟).
          • 注冊上述的 schema 和 handler。

          既然只要按照這四步來,那我們就照著這個(gè)文檔來自己實(shí)現(xiàn)一個(gè)。

          Authoring the Schema

          編寫一個(gè)javajr.xsd 放入項(xiàng)目的resources/META-INF文件夾里面(這個(gè)也可以是其他路徑)

          <?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的地址后面有用到。
          • 這里我們就定義了一個(gè)元素application 里面有兩個(gè)屬性分別為websiteweixin。
          編寫一個(gè) NamespaceHandler
          package org.spring.demo.schema;
          import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
          public class MyNamespaceHandler extends NamespaceHandlerSupport {
              @Override
              public void init() {
               // 這個(gè)名字也不是隨便取的,上面編寫xsd的根節(jié)點(diǎn)元素的name, <xsd:element name="application">
                  registerBeanDefinitionParser("application", new MyBeanDefinitionParser());
              }
          }

          這個(gè)NamespaceHandler 就是將一個(gè) XML 節(jié)點(diǎn)解析成 IOC 容器中的一個(gè)實(shí)體類。也就是說相當(dāng)于在xml里面的配置的對象,通過Spring ioc 容器管理起來了

          編寫 BeanDefinitionParser 的實(shí)現(xiàn)類
          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 elementBeanDefinitionBuilder 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);
                  }
              }
          }

          上面在這個(gè)實(shí)現(xiàn)類只是簡單的做了一個(gè)賦值操作,你如果需要有自己的邏輯業(yè)務(wù)也可以自行來實(shí)現(xiàn)。上面還有一個(gè)JavajrDomain這個(gè)實(shí)體類就不貼代碼,就一個(gè)簡單的javabean里面包含了兩個(gè)屬性weixin和website。

          注冊schema組件

          最后在resources/META-INF目錄下添加兩個(gè)配置文件(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

          在這個(gè)地方的時(shí)候我們其實(shí)可以以版本號來進(jìn)行命名,方便我們可以使用多個(gè)不同的版本,Spring-beans 就是這么玩的。

          測試自定義schema

          • resources 目錄下新建一個(gè)applicationContext.xml文件這個(gè)文件就是使用下我們我們自己自定義的schema,這個(gè)文件需要注意的就是上面標(biāo)紅的這幾行,一般如果我們有引入過第三方的框架,比如mq、或者dubbo等它們都有自定義的這些玩意。

          • 編寫一個(gè)啟動類

          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'}
          • 到這里我們自己實(shí)現(xiàn)的一個(gè) XML schema 就完成了,是不是很簡單,只要照著官方文檔擼就可以了。照著擼的過程可能有幾個(gè)小細(xì)節(jié)需要注意下引入 XML schema 的時(shí)候需要注意下空格,或者一些特殊符號。上述代碼已經(jīng)提交到了gitee上https://gitee.com/javajr/spring-schema-demo 感興趣的朋友可以直接下載下來run下,不過還是不建議這么玩,最好還是自己動手去嘗試下,畢竟也就四步,照著文檔來。

          Dubbo 中的 XML schema 擴(kuò)展

          在文章開始的時(shí)候我們有介紹dubbo 自定義的XML schema ,下面我們一起打開dubbo源碼看看它是如何來實(shí)現(xiàn)的,看下面這個(gè)截圖,也是按照那四步來的。

          SpringBoot的starter

          現(xiàn)在有了SpringBoot 之后以前用這個(gè) XML schema配置的框架,大多數(shù)都會有對應(yīng)的starter來進(jìn)行封裝,starter的使用比起 XML schema的使用還是簡單多了,開箱即用,無需編寫很多的配置文件。如果不是很清楚SpringBootstarter的推薦去看看這兩篇文章《面試高頻題:springBoot自動裝配的原理你能說出來嗎?》《保姆級教程,手把手教你實(shí)現(xiàn)一個(gè)SpringBoot的starter》。

          總結(jié)

          雖然現(xiàn)在XML schema 擴(kuò)展用的不多了,但是應(yīng)該也還有比較老的項(xiàng)目在使用吧,如果還是比較老的項(xiàng)目,需要引入一個(gè)什么樣的框架,我們至少需要知道需要怎么去引入,網(wǎng)上雖然有很多文章可以借鑒,但是我們也應(yīng)該知其然知其所以然。而不是直接把配置文件單純的copy過來。我們應(yīng)該知道為啥需要copy這個(gè)xsd,為什么沒有這個(gè)xsd ,idea不糊識別會報(bào)錯(cuò)。

          結(jié)束

          • 由于自己才疏學(xué)淺,難免會有紕漏,假如你發(fā)現(xiàn)了錯(cuò)誤的地方,還望留言給我指出來,我會對其加以修正。
          • 如果你覺得文章還不錯(cuò),你的轉(zhuǎn)發(fā)、分享、贊賞、點(diǎn)贊、留言就是對我最大的鼓勵。
          • 感謝您的閱讀,十分歡迎并感謝您的關(guān)注。


          巨人的肩膀摘蘋果:
          https://javajr.cn
          https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#xml-custom https://www.cnkirito.moe/spring-xsd/#%E5%89%8D%E8%A8%80

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

          點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

          在看點(diǎn)這里好文分享給更多人↓↓

          瀏覽 33
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美性操| 我要看操逼片 | 夜夜爽天天爽 | 国产精品久久久久久久久久王安宇 | 超碰综合在线 |