Spring下自定義xml標籤

dubbo自定義了很多xml標籤,例如<dubbo:application>,那麼這些自定義標籤是怎麼與spring結合起來的呢?我們先看一個簡單的例子。

一 編寫模型類

複製代碼
 1 package com.hulk.testdubbo.model;
 2 
 3 public class Hero {
 4     private  String name;
 5     private  int    age;
 6 
 7     public String getName() {
 8         return name;
 9     }
10 
11     public void setName(String name) {
12         this.name = name;
13     }
14 
15     public int getAge() {
16         return age;
17     }
18 
19     public void setAge(int age) {
20         this.age = age;
21     }
22 }
複製代碼

 

二 定義xsd文件

複製代碼
 1 <xsd:schema
 2         xmlns="http://hulk.com/schema"
 3         xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 4         targetNamespace="http://hulk.com/schema">
 5     <xsd:complexType name="elementname1complexType">
 6         <xsd:attribute name="name" type="xsd:string">
 7             <xsd:annotation>
 8                 <xsd:documentation><![CDATA[ The elementname1 name. ]]></xsd:documentation>
 9             </xsd:annotation>
10         </xsd:attribute>
11         <xsd:attribute name="age" type="xsd:int">
12             <xsd:annotation>
13                 <xsd:documentation><![CDATA[ The elementname1 age. ]]></xsd:documentation>
14             </xsd:annotation>
15         </xsd:attribute>
16     </xsd:complexType>
17 
18     <xsd:element name="elementname1" type="elementname1complexType">
19         <xsd:annotation>
20             <xsd:documentation><![CDATA[ elementname1的文檔 ]]></xsd:documentation>
21         </xsd:annotation>
22     </xsd:element>
23 </xsd:schema>
複製代碼

說明:

  • 定義targetNamespace(目標命名空間),xmlns的值要與這個相同
  • xsd:element定義的就是將來會在xml文件中用到的元素,例如<dubbo:application>中的application
  • xsd:attribute定義的就是模型類中的屬性,例如<dubbo:application name=”xxx”>中的name,並且可以指定屬性類型,進而起到檢測的作用(當我們定義的是int,如果在xml中的值是非int型的,直接會報錯)。

 

三 編寫spring.schemas

作用:該文件用來指定xsd文件的位置。

http\://hulk.com/schema/hero.xsd=META-INF/hero.xsd

注意:紅色部分要與xsd文件中的targetNamespace相同。

 

四 編寫BeanDefinition解析器

作用:主要用來解析自定義的xml標籤。

複製代碼
 1 package com.hulk.testdubbo.schema;
 2 
 3 import org.springframework.beans.factory.config.BeanDefinition;
 4 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 5 import org.springframework.beans.factory.support.RootBeanDefinition;
 6 import org.springframework.beans.factory.xml.BeanDefinitionParser;
 7 import org.springframework.beans.factory.xml.ParserContext;
 8 import org.w3c.dom.Element;
 9 
10 public class HeroBeanDefinitionParser implements BeanDefinitionParser {
11     private final Class<?> beanClass;
12 
13     public HeroBeanDefinitionParser(Class<?> beanClass) {
14         this.beanClass = beanClass;
15     }
16 
17     public BeanDefinition parse(Element element, ParserContext parserContext) {
18         RootBeanDefinition beanDefinition = new RootBeanDefinition();
19         beanDefinition.setBeanClass(beanClass);
20         beanDefinition.setLazyInit(false);
21         beanDefinition.getPropertyValues().add("name", element.getAttribute("name"));
22         beanDefinition.getPropertyValues().add("age", element.getAttribute("age"));
23         BeanDefinitionRegistry beanDefinitionRegistry = parserContext.getRegistry();
24         beanDefinitionRegistry.registerBeanDefinition(beanClass.getName(),beanDefinition);//註冊bean到BeanDefinitionRegistry中
25         return beanDefinition;
26     }
27 }
複製代碼

 

五 編寫命名空間處理器

作用:主要用來註冊BeanDefinition解析器。

複製代碼
 1 package com.hulk.testdubbo.schema;
 2 
 3 import com.hulk.testdubbo.model.Hero;
 4 import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
 5 
 6 public class HeroNamespaceHandler extends NamespaceHandlerSupport {
 7     public void init() {
 8         registerBeanDefinitionParser("elementname1", new HeroBeanDefinitionParser(Hero.class));
 9     }
10 }
複製代碼

說明:通常爲每一個xsd:element都要註冊一個BeanDefinitionParser。

 

六 編寫spring.handlers文件

作用:主要用於關聯命名空間處理器和xsd中的targetNamespace。

http\://hulk.com/schema=com.hulk.testdubbo.schema.HeroNamespaceHandler

說明:key是xsd文件中的targetNamespace。

 

七 測試 - 編寫hero.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:hero="http://hulk.com/schema"
5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
6        http://hulk.com/schema http://hulk.com/schema/hero.xsd">
7     <hero:elementname1 name="xiaona" age="18"/>
8 </beans>
複製代碼

說明:

  • xmlns:hero的value是xsd文件中的targetNamespace。
  • xmlns:hero可以寫成xmlns:xxx,此時<hero:elementname1/>就要寫成<xxx:elementname1/>

 

八 測試 - 編寫測試主類

複製代碼
 1 package com.hulk.testdubbo.test;
 2 
 3 import com.hulk.testdubbo.model.Hero;
 4 import org.springframework.context.ApplicationContext;
 5 import org.springframework.context.support.ClassPathXmlApplicationContext;
 6 
 7 public class Main {
 8     public static void main(String[] args) {
 9         ApplicationContext applicationContext = new ClassPathXmlApplicationContext("hero.xml");
10         Hero hero = (Hero) applicationContext.getBean(Hero.class.getName());
11         System.out.println("name: " + hero.getName() + " age: " + hero.getAge());
12     }
13 }
複製代碼

 

如何在spring中自定義xml標籤的方法就結束了。在實際中,隨着註解和javaconfg的盛行,xml的方式漸漸的會淡出舞臺,但是spring的啓動流程還是會的。來看一下上述代碼涉及到的流程。

  • 使用ResourceLoader將配置文件xml裝載爲Resource對象;
  • 使用BeanDefinitionReader解析配置信息:將每一個<bean>解析爲一個BeanDefinition對象,然後存儲到BeanDefinitionRegistry中
    • 實際上是BeanDefinitionReader調用BeanDefinitionParser進行了解析操作,解析完成後註冊到BeanDefinitionRegistry(代碼看上邊的HeroBeanDefinitionParser)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章