自己構建一個Spring自定義標籤以及原理講解
平時不論是在Spring配置檔案中引入其他中介軟體(比如dubbo),還是使用切面時,都會用到自定義標籤。那麼配置檔案中的自定義標籤是如何發揮作用的,或者說程式是如何通過你新增的自定義標籤實現相應的功能的呢?且看下文。
通過對本文的閱讀,你會在閱讀涉及到自定義標籤的原始碼功能時事半功倍,而且還可以自己動手做出一個自己的自定義標籤。
先呈上我自己在本地實現自定義標籤的程式碼及對應講解:
1、先無腦輸出一個測試要用到的Bean類
1 public class User { 2 3private String userName; 4private String emailAddress; 5 6public String getUserName() { 7return userName; 8} 9 10public void setUserName(String userName) { 11this.userName = userName; 12} 13 14public String getEmailAddress() { 15return emailAddress; 16} 17 18public void setEmailAddress(String emailAddress) { 19this.emailAddress = emailAddress; 20} 21 } View Code
2、spring的xml配置檔案,以及在配置檔案中引入自定義標籤跟它的名稱空間
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4xmlns:context="http://www.springframework.org/schema/context" 5xmlns:aop="http://www.springframework.org/schema/aop" 6xmlns:mvc="http://www.springframework.org/schema/mvc" 7xmlns:myname="http://www.zzq.com/schema/user" 8xsi:schemaLocation="http://www.springframework.org/schema/beans 9http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 10http://www.springframework.org/schema/context 11http://www.springframework.org/schema/context/spring-context-4.0.xsd 12http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd 13http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 14http://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="[email protected]"/> 22 23 </beans> View Code
3、從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。
中間http://www.zzq.com/schema/user對應此自定義標籤的handler,放在Spring.handlers中。
最後的http://www.zzq.com/schema/user.xsd則定義了此自定義標籤的XXX,即自定義標籤冒號後面有什麼,由此xsd定義,放在Spring.schemas中。
Spring.handlers跟Spring.schemas檔案都放在META-INF目錄下,因為spring會預設去此目錄下讀。
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 12protected Class getBeanClass(Element element) { 13return User.class; 14} 15 16@Override 17protected void doParse(Element element, BeanDefinitionBuilder builder) { 18String name = element.getAttribute("userName"); 19String address = element.getAttribute("emailAddress"); 20 21if (StringUtils.hasText(name)) { 22builder.addPropertyValue("userName", name); 23} 24if (StringUtils.hasText(address)) { 25builder.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 7public void init() { 8registerBeanDefinitionParser("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
此檔案規定了自定義註解的標籤,以及對應的屬性
4、測試類ElementTest
1 package myDemoHome.springElement; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 public class ElementTest { 7public static void main(String[] args) { 8ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath*:spring/spring-config.xml"); 9User user = (User)applicationContext.getBean("testUserBean"); 10System.out.println(user.getEmailAddress()); 11} 12 } View Code
再附上一張所用類的位置關係圖
至此大功告成,最後執行一下測試類:
功德圓滿!
總結:
構建一個自定義標籤的流程便是如此,相信如果後面再遇到自定義標籤,按照此構建思路反向解析一下便也能順藤摸瓜知曉它的來龍去脈。其實看一下之前我們用過的中介軟體,像dubbo,也是一樣的套路,只是功能更繁雜。
dubbo的jar包如圖所示:
也是用了這三個實現的標籤引用。
寫在最後:至此,19年金三銀四找工作之途的總結(包括技術跟個人感悟,感興趣的道友可以移步我的另幾篇博文一探究竟)便告一段落。今年自從去年下半年的資本收縮後,行情確實相較以往差了一些(雖然貧道也才17年入行),但我個人的感覺
是行業整體迴歸理性,之前是經過三四個月培訓班下來就月薪十幾K而且都搶著招人,太不正常。話說回來,不管外界行情怎樣,只要你喜歡做這一行,都要靜下心來多學習多探究,才能在不斷的積累中讓自己更上一層。今年年初兩次阿里的面試
經歷也讓自己對於自身能力有了更客觀真實的認識,不管是從專案經歷還是個人技術積累上,都差很多。目前貧道新公司所處的部門,對技術比較注重,且技術大佬不少,工作都很認真,正是"發糞塗牆"之際,內心充滿激情。後面的博文目前打算
更多偏向微服務(因為目前公司的專案用的就是微服務架構)、併發程式設計(因為前段時間買了本併發程式設計實戰)。技術積累不是一朝一夕,與各位道友共勉!