Spring中xml自定義標籤的實現流程

Spring中xml自定義標籤的實現流程

背景
雖然xml方式在現在看來有一些落後了,但畢竟是註解的一種過渡。而解析器不管是註解還是xml都是一致的。

例如:dubbo大量的自定義標籤,包括spring中也存在大量的標籤(低版本xml方式),那麼自定義標籤在Spirng中是如何實現的,今天就來理一下流程。


一、實現步驟先知

  1. 編寫一個XSD: 定義需要使用到的標籤
  2. 編寫一個解析標籤的BeanDefinitionParse: 解析這些標籤,將會做什麼操作
  3. 編寫一個Handler,將自定義的BeanDefinitionParse進行註冊: 將其註冊到Map集合中。
  4. 編寫spring.handlers 和 spring.schemas 兩個文件:分別告訴handler 和 schema的位置。
  5. 編寫一個應用程序驗證

二、自定義標籤實現

模擬<context:component-scan/> 實現註解掃描操作;實現標籤<uzong:component-scan/>
話不多說,直接開始吧

工程結構如下:
在這裏插入圖片描述


2.1 編寫xsd

模擬context,編寫一份自己的xsd。名稱:uzong.xsd

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
		targetNamespace="http://www.springframework.org/schema/uzong"
		elementFormDefault="qualified">
	<xsd:element name="component-scan">
		<xsd:complexType>
			<xsd:attribute name="base-package" type="xsd:string">
				<xsd:annotation>
					<xsd:documentation><![CDATA[
			The comma/semicolon/space/tab/linefeed-separated list of packages to scan for annotated components.
							]]></xsd:documentation>
				</xsd:annotation>
			</xsd:attribute>
		</xsd:complexType>
	</xsd:element>
</xsd:schema>

關鍵元素:base-package;指定路徑包名


2.2 編寫自己的parse

下面的代碼主要邏輯就是獲取basePackage路徑,然後使用ClassPathBeanDefinitionScanner 進行掃描註解。關於掃描器的使用不是本篇重點,可以跳過。


public class UzongComponentScanBeanDefinitionParse implements BeanDefinitionParser {

	@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		//1. 獲取value
		String basePackage = element.getAttribute("base-package");//僅解析:base-package
		//2. 解析獲取basePackage
		basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
		// 3. 字符串分割
		String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
				ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
		//4. 獲取掃描器
		ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), true);
		//5. 掃描註冊
		scanner.scan(basePackages);
		return null;
	}

	protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
		return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,
				readerContext.getEnvironment(), readerContext.getResourceLoader());
	}

}

在完成了我們的parse後,需要編寫Handler來註冊parse到Spring的集合中


2.3 註冊handler 到集合

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class UzongContextNamespaceHandler extends NamespaceHandlerSupport {
	@Override
	public void init() {
		registerBeanDefinitionParser("component-scan",new UzongComponentScanBeanDefinitionParse());
	}
}

registerBeanDefinitionParser 實質就是將其放入map中;NamespaceHandlerSupport 中的parsers


2.4 spring.handlers 和 spring.schemas

spring.handlers

http\://www.springframework.org/schema/uzong=uzong.parse.UzongContextNamespaceHandler

spring.schemas

http\://www.springframework.org/schema/uzong.xsd=META-INF/uzong.xsd

完成上面步驟後,基本上已經完成自定義標籤的實現流程了,接下進行驗證


2.5 驗證

編寫xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:uzong="http://www.springframework.org/schema/uzong"
	   xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		   http://www.springframework.org/schema/uzong http://www.springframework.org/schema/uzong.xsd">
		   
	<uzong:component-scan base-package="uzong.parse"/>

</beans> 

其中Apple 爲一個bean

@Component
public class Apple {
	private String name = "apple";

	public Apple() {
	}

	@Override
	public String toString() {
		return "Apple{" +
				"name='" + name + '\'' +
				'}';
	}

	public Apple(String name) {
		this.name = name;
	}
}
public class App {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("application-uzong.xml");
		// 從容器中獲取bean
		Apple apple = (Apple) ac.getBean("apple");
		System.out.println(apple);
	}
}

運行結果如下:

Apple{name='apple'}

2.6 小結

通過以上幾個步驟,就完成了自定義標籤的實現流程。不過這種xml的方式是否已經比較過時了;現在多采用註解方式。但是,註解和xml的解析本質都是一樣的。重點都是在parse這個類上面。

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