本身構建一個Spring自定義標籤以及原理講解

    平時不管是在Spring配置文件中引入其餘中間件(好比dubbo),仍是使用切面時,都會用到自定義標籤。那麼配置文件中的自定義標籤是如何發揮做用的,或者說程序是如何經過你添加的自定義標籤實現相應的功能的呢?且看下文。面試

經過對本文的閱讀,你會在閱讀涉及到自定義標籤的源碼功能時事半功倍,並且還能夠本身動手作出一個本身的自定義標籤。spring

     先呈上我本身在本地實現自定義標籤的代碼及對應講解:編程

一、先無腦輸出一個測試要用到的Bean類spring-mvc

 1 public class User {
 2 
 3     private String userName;
 4     private String emailAddress;
 5 
 6     public String getUserName() {
 7         return userName;
 8     }
 9 
10     public void setUserName(String userName) {
11         this.userName = userName;
12     }
13 
14     public String getEmailAddress() {
15         return emailAddress;
16     }
17 
18     public void setEmailAddress(String emailAddress) {
19         this.emailAddress = emailAddress;
20     }
21 }
View Code

 二、spring的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:context="http://www.springframework.org/schema/context"
 5        xmlns:aop="http://www.springframework.org/schema/aop"
 6        xmlns:mvc="http://www.springframework.org/schema/mvc"
 7        xmlns:myname="http://www.zzq.com/schema/user"
 8        xsi:schemaLocation="http://www.springframework.org/schema/beans
 9       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
10       http://www.springframework.org/schema/context
11       http://www.springframework.org/schema/context/spring-context-4.0.xsd
12       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
13       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
14       http://www.zzq.com/schema/user http://www.zzq.com/schema/user.xsd">
15 
16     <aop:aspectj-autoproxy proxy-target-class="true"/>
17     <mvc:annotation-driven/>
18     <context:component-scan base-package="myDemoHome"/>
19     <context:property-placeholder location="classpath:properties/config.properties" ignore-unresolvable="true"/>
20 
21     <myname:myPw id="testUserBean" userName="zzq" emailAddress="zzqing@110.com"/>
22 
23 </beans>
View Code

三、從2中能夠看到,命名空間中我添加了自定義的xmlns:myname="http://www.zzq.com/schema/user",以及http://www.zzq.com/schema/user跟http://www.zzq.com/schema/user.xsd。併發

其中緊跟xmlns冒號後面的部分,就是咱們自定義標籤引號前的部分,好比此處定義了myname,那麼自定義標籤中我就能夠<myname:XXX/>這樣引用了,其中的XXX則是在命名空間中定義的myPw。mvc

中間http://www.zzq.com/schema/user對應此自定義標籤的handler,放在Spring.handlers中。app

最後的http://www.zzq.com/schema/user.xsd則定義了此自定義標籤的XXX,即自定義標籤冒號後面有什麼,由此xsd定義,放在Spring.schemas中。dom

Spring.handlers跟Spring.schemas文件都放在META-INF目錄下,由於spring會默認去此目錄下讀。ide

Spring.handlers以下所示:

http\://www.zzq.com/schema/user=myDemoHome.springElement.bdParser.UserNamespaceHandler

Spring.schemas以下所示:

http\://www.zzq.com/schema/user.xsd=META-INF/spring-test.xsd

3.1  自定義標籤的解析類UserNamespaceHandler構建

 1 package myDemoHome.springElement.bdParser;
 2 
 3 import myDemoHome.springElement.User;
 4 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 5 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
 6 import org.springframework.util.StringUtils;
 7 import org.w3c.dom.Element;
 8 
 9 public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
10 
11     @Override
12     protected Class getBeanClass(Element element) {
13         return User.class;
14     }
15 
16     @Override
17     protected void doParse(Element element, BeanDefinitionBuilder builder) {
18         String name = element.getAttribute("userName");
19         String address = element.getAttribute("emailAddress");
20 
21         if (StringUtils.hasText(name)) {
22             builder.addPropertyValue("userName", name);
23         }
24         if (StringUtils.hasText(address)) {
25             builder.addPropertyValue("emailAddress", address);
26         }
27     }
28 
29 }
View Code

就是對element中的標籤進行解析處理,完成從xml中的標籤屬性向對象值的轉化

3.2 自定義標籤解析類的註冊 UserNamespaceHandler

 1 package myDemoHome.springElement.bdParser;
 2 
 3 import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
 4 
 5 public class UserNamespaceHandler extends NamespaceHandlerSupport {
 6     @Override
 7     public void init() {
 8         registerBeanDefinitionParser("myPw", new UserBeanDefinitionParser());
 9     }
10 }
View Code

此處的意思就是當遇到myPw這個標籤的時候,往spring容器中注入這個標籤的解析類,以完成後續對標籤屬性的解析。看到此處,各位道友有沒有想起AOP的自定義註解aspectj-autoproxy 的解析呢?其實套路都是同樣的。

3.3 xsd文件spring-test.xsd的定義

<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.zzq.com/schema/user"
        elementFormDefault="qualified">

    <element name="myPw">
        <complexType>
            <attribute name="id" type="string"/>
            <attribute name="userName" type="string"/>
            <attribute name="emailAddress" type="string"/>
        </complexType>
    </element>
</schema>
View Code

此文件規定了自定義註解的標籤,以及對應的屬性

四、測試類ElementTest

 1 package myDemoHome.springElement;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class ElementTest {
 7     public static void main(String[] args) {
 8         ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath*:spring/spring-config.xml");
 9         User user = (User)applicationContext.getBean("testUserBean");
10         System.out.println(user.getEmailAddress());
11     }
12 }
View Code

再附上一張所用類的位置關係圖

至此大功告成,最後運行一下測試類:

功德圓滿!

總結:

構建一個自定義標籤的流程即是如此,相信若是後面再遇到自定義標籤,按照此構建思路反向解析一下便也能順藤摸瓜知曉它的前因後果。其實看一下以前咱們用過的中間件,像dubbo,也是同樣的套路,只是功能更繁雜。

dubbo的jar包如圖所示:

也是用了這三個實現的標籤引用。

寫在最後:至此,19年金三銀四找工做之途的總結(包括技術跟我的感悟,感興趣的道友能夠移步個人另幾篇博文一探究竟)便告一段落。今年自從去年下半年的資本收縮後,行情確實相較以往差了一些(雖然貧道也才17年入行),但我我的的感受

是行業總體迴歸理性,以前是通過三四個月培訓班下來就月薪十幾K並且都搶着招人,太不正常。話說回來,無論外界行情怎樣,只要你喜歡作這一行,都要靜下心來多學習多探究,才能在不斷的積累中讓本身更上一層。今年年初兩次阿里的面試

經歷也讓本身對於自身能力有了更客觀真實的認識,無論是從項目經歷仍是我的技術積累上,都差不少。目前貧道新公司所處的部門,對技術比較注重,且技術大佬很多,工做都很認真,正是"發糞塗牆"之際,心裏充滿激情。後面的博文目前打算

更多偏向微服務(由於目前公司的項目用的就是微服務架構)、併發編程(由於前段時間買了本併發編程實戰)。技術積累不是一朝一夕,與各位道友共勉!

相關文章
相關標籤/搜索