1. 程式人生 > >Spring自定義標籤的解析

Spring自定義標籤的解析

一:專案demo

Spring提供了可擴充套件的支援,利用如下的程式碼來一步步實現spring自定義解析。
專案結構如下,引入spring4.0
在這裡插入圖片描述

1.建立一個user物件

public class User {

    private String userName;
    private String email; 
    ...............省略getset
}

2.建立一個XSD檔案,用於校驗自定義xml檔案

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.lexueba.com/schema/user"
        xmlns:tns="http://www.lexueba.com/schema/user"
        elementFormDefault="qualified">
    <element name="user">
        <complexType>
            <attribute name="id" type="string"/>
            <attribute name="userName" type="string"/>
            <attribute name="email" type="string"/>
        </complexType>
    </element>
</schema>

3.建立解析類:UserBeanDefinitionParser 繼承AbstractSingleBeanDefinitionParser

public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    //element對應的類
    @Override
    protected Class getBeanClass(Element element) {
        return User.class;
    }

    //從element中解析並提取對應的元素
    @Override
    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        String userName = element.getAttribute("userName");
        String email = element.getAttribute("email");
        
        //將提取的資料放入到BeanDefinitionBuilder,待完成所有bean的解析後統一註冊到beanfatory中
        if (StringUtils.hasText(userName)) {
            bean.addPropertyValue("userName", userName);
        }
        if (StringUtils.hasText(email)) {
            bean.addPropertyValue("email", email);
        }
    }

}

4.建立handle,用於將bean注入到spring容器

public class UserNamespaceHandler extends NamespaceHandlerSupport{

    @Override
    public void init() {
    //此處用於解析出來的user標籤交由UserBeanDefinitionParser去處理
        registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
    }
}

5.建立handle對映檔案,Spring.handlers,以及Spring.schemas用於對xml檔案進行校驗

Spring.handlers

http\://www.lexueba.com/schema/user=spring.tag.handle.UserNamespaceHandler

Spring.schemas

http\://www.lexueba.com/schema/user.xsd=META-INF/user.xsd

6.建立spring配置檔案Spring.xml
注意:beans中的引數需同上handle和schemas相匹配

<?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:usertag="http://www.lexueba.com/schema/user**"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
         **http://www.lexueba.com/schema/user http://www.lexueba.com/schema/user.xsd**">
    
    <usertag:user id="user" userName="cosmos" email="[email protected]"/>

</beans>

6.至此,自定義解析步驟完成,開始測試。

public class CustomTagApplication {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        ApplicationContext bf = new ClassPathXmlApplicationContext("spring/tag/xml/Spring.xml");
        User user = (User) bf.getBean("user");
        System.out.println(user);
    }
}

結果如下:
在這裡插入圖片描述

二:原理詳解

在之前bean解析的時候,有兩種方式,如下
在這裡插入圖片描述

自定義標籤會呼叫parseCustomElement方法,parseCustomElement程式碼如下:
名稱空間即為spring.xml中的usertag
在這裡插入圖片描述

通過DefalutNamespaceHandleResolver來載入該bean的處理類,進入DefalutNamespaceHandleResolver下的resolve方法:
在這裡插入圖片描述

載入完handle後,則進入具體的解析過程,呼叫handle的parse方法。此處的parse方法引用的是父類AbstractBeanDefinitionParser的方法,程式碼如下
在這裡插入圖片描述

此處,parseInternal會對bean進行進一步的處理:
在這裡插入圖片描述

到此,自定義標籤的解析就結束了。