Spring xml 解析擴展

Spring 配置文件xml 是可以通過註冊命名空間來達到解析擴展的。也就是說 AOP、TX、等都是通過擴展命名空間來解析數據的。定義自己的命名解析需要有幾個步驟,主要採用策略模式進行開發,Github實例代碼:https://github.com/JerryDai90/java-case/tree/master/spring/xml-extension

1. 自定義 DefinitionParser

需要定義解析 xml DefinitionParser,如 ConfigBeanDefinitionParser.java

2、定義 Handler

定義 Handler,此類用於註冊到 Spring 處理類池裏面,裏面需要在 init 方法中註冊實現類。

比如AOP就定義了configaspectj-autoproxyscoped-proxyspring-configured這些元素就使用

public class AopNamespaceHandler extends NamespaceHandlerSupport {
	@Override
	public void init() {
		// In 2.0 XSD as well as in 2.1 XSD.
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace as of 2.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}
}

3. 定義 xml 命名空間

比如AOP 的命名空間 xmlns:aop="http://www.springframework.org/schema/aop"

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

與 DSD 文件定義

4、添加 spring.handlers、spring.schemas 文件

需要在MATE-INF 中 增加 spring.handlers 文件。命名空間需要指定 Handler 類。

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

需要在MATE-INF 中 增加 spring.schemas 文件,對應命名空間對應的xsd文件。

5. 關鍵類

DefaultNamespaceHandlerResolver:解析加載到ClassLoader裏面的 spring.handlers 文件。
NamespaceHandlerSupport:註冊標籤對應的解析類

6. 小結

這樣就可完成擴展Spring xml 的解析並且實現相應的業務。大概劃的處理圖。標準的配置流程可以參考 spring-aop-5.2.3.RELEASE.jar 配置。
w400

  • spring 初始化的時候就會去ClassLoader找到所有的 META-INF/spring.handlers 文件。
  • 加載文件中的 Handler,調用 init 進行初始化(這裏初始化就直接映射了命名空間與 element 之間的關係)。
  • 真正解析的的時候拿到當前的 element 後,即可後去其命名空間,通過命名空間找到相應的 parser 對象進行解析。

7. 其他

debug 看代碼的時候,斷點DefaultNamespaceHandlerResolver#getHandlerMappings() 方法裏面的時候,handlerMappings 成員變量都是有值的。以爲有什麼黑魔法,百思不得解。最後發現另外以爲大神也遇到,附上鍊接:https://www.cnblogs.com/developer_chan/p/10002492.html

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