品Spring:帝國的基石
序
生活是一杯酒,有時需要麻醉自己,才能夠暫時忘卻痛苦與不快。
生活是一杯茶,有時需要細細品味,才發現苦澀背後也會有甘甜。
Spring是一杯酒,一眼望不到邊的官方文件,著實讓人難以下嚥。
Spring是一杯茶,在無邊的原始碼中暢遊之後,發現色相味道俱全。
高考狀元是六月份的網紅,Spring帝國是Java界的明星。
狀元有自己的“武功祕籍”,Spring有自己的“帝國基石”。
請隨本文一起,品Spring,尋找帝國的基石。
帝國的基石
無論是大到一個國家,或是小到一個個人,都有自己賴以存在的基石。這個基石就是核心支柱,就像經濟基礎支撐著上層建築。
以BAT來說,百度的搜尋,阿里的電商,騰訊的社交。可以說這是他們的立司之本,如果想在這些方面和他們PK,幾乎沒有勝算的可能。
Spring絕對是Java開發領域中一顆閃耀的明星,它的巨大光芒甚至一直在引領著Java的發展方向。
現在說它已經發展為一個帝國,應該不會有人站出來反對吧。嗯,站出來也沒關係,本人不接受反對。哈哈。
那麼有一個問題,請大家思考下,Spring帝國的基石是什麼?
用過或瞭解Spring的人肯定都會說是IoC啦,AOP啦,宣告式事務啦等等。只能說這些回答浮於表面,明顯不走心啊。
好了,我來公佈答案吧,這個帝國的基石,其實就是Bean。肯定會有人問,這個bean是什麼東西啊,那就去看它的定義吧。對,就是Spring中的bean定義。
在Spring中,bean定義其實就是一個介面,即BeanDefinition。我在上一篇“畢業十年”的文章中說過,我們定義的類或介面其實都是對一種資料構成的描述,所以可以直接把類或介面看作是一種資料結構。
那麼bean定義介面,就是一種資料結構,它記錄了一個bean的全部資訊,後期Spring對這個bean的所有操作都是建立在這些資訊之上的。
如果對Spring不是很熟悉的朋友,聽到“bean的全部資訊”這句話會有點懵。不要擔心,照例拿生活中我們熟悉的事物去做類比,爭取讓所有人都能明白。
在醫療行業,每個患者都會有一個病歷,上面記錄了患者家族病史,患者個人病史,都做過哪些檢查以及檢查結果,都做過哪些治療以及恢復情況。還有大夫每次對患者的病情診斷與分析。
這些資訊肯定是記錄的越全面越好,後續的治療方案都是依賴這些資訊而制定的。Spring中bean的資訊就對等於這裡患者的病歷資訊。
在公安系統,每個嫌疑人也會有一個檔案,上面記錄了他的口供,作案資訊或一些其它證據,同樣這些資訊蒐集的越全面越好,後期法官的宣判與量刑也都依賴於它。
那麼在這裡,記錄案件資訊的檔案,就可以對等於Spring中bean的資訊。
相信通過這兩個示例,你已經完全明白了這個bean資訊的作用和地位。雖然到目前為止,你可能還真不知道它裡面到底儲存的是什麼資訊。但這不要緊,只要記住它非常重要就可以了。
趁著這個機會,再小小拓展一下:
這裡的病歷資訊和檔案資訊裡面記錄的都是一些資料,所以可以認為它們對應於程式中的資料結構。
醫生的治療方案和法官的宣判,其實都是依賴這些資料做出的決定,因此可以認為它們對應於程式中的演算法。
可見,資料結構決定著演算法,或者說,演算法是基於資料結構而設計的。
因此,可以說資料結構的重要性要大於演算法。良好的資料結構能簡化演算法,不好的資料結構只能使演算法變得更復雜。
跟著變化走,把它當朋友
在上篇文章中提到過,唯一不變的就是變化,所以隨著時間的推移,只需不斷往這個資料結構中補充新的bean資訊,Spring再利用這些補充資訊去定義新的操作,以適應發展的需要。
就是這樣,Spring一步一步成長為一個浩浩蕩蕩的帝國。就像我在上一遍文章中說的,類或介面這樣的資料結構一定要進行精心設計,這樣程式碼寫起來會簡單些,而且後期改起來也會容易些。
一個非常明顯的例子,一開始都是基於XML配置檔案的,現在都是基於註解或Java配置的,可以說Spring完成了一次華麗的轉身,而且非常完美絲滑,沒有一點拖泥帶水。
其實就是在bean定義資料結構中加入了註解和Java配置相關的資訊,Spring利用這些資訊去重新實現一遍,並且和基於XML的實現並存,因此既可以用XML也可以用註解。
就像我在上一篇文章中說的,一定要合理抽象,從巨集觀整體把握,良好定義整體架構或結構,至於一些具體的區域性實現細節,可以根據實際情況來定。
因為區域性實現涉及範圍一般較小,後期換用新的方式來個重新實現也會相對容易一些。從XML到註解基本就是這樣子的。
其實說實話,上一篇文章就是從這一篇分離出去的,專門為本篇文章埋伏筆、做鋪墊用的。哈哈。
滔滔不絕的說了這麼多,快來看看廬山真面目吧。
最討厭的就是原始碼
有句話是怎麼說的呢,“要不是為了生活,誰願意把自己弄得滿身才華”。哈哈,看原始碼時多想想這句話。
不想看的,直接跳過吧。
BeanDefinition介面,及bean定義,下面只列出了get方法,其實還有set方法:
bean定義可以繼承
String getParentName();
bean對應的類名稱,用來例項化bean
String getBeanClassName();
生命週期範圍
String getScope();
是否延遲例項化
boolean isLazyInit();
依賴的其它bean
String[] getDependsOn();
是否作為自動裝配候選bean
boolean isAutowireCandidate();
是否是主要的,用在可能有多個候選bean的情況
boolean isPrimary();
一個用來生成該bean的工廠bean名稱
String getFactoryBeanName();
一個用來生產該bean的工廠方法名稱
String getFactoryMethodName();
bean的建構函式
ConstructorArgumentValues getConstructorArgumentValues();
一些key/value,可以在bean例項化後設置給bean的屬性
MutablePropertyValues getPropertyValues();
初始化方法名稱
String getInitMethodName();
銷燬方法名稱
String getDestroyMethodName();
角色,應用層/基礎設施層
int getRole();
人類可讀的描述
String getDescription();
是否單例
boolean isSingleton();
是否原型
boolean isPrototype();
是否抽象
boolean isAbstract();
這兩點比較關鍵,需要知道:
可以有兩種方法來指定一個bean的定義,一個是類名稱,一個是工廠方法。
單例和原型這兩種生命週期不是互斥關係,因為存在既不是單例也不是原型的,如request、session等範圍。
AnnotatedBeanDefinition介面,擴充套件了bean定義介面,增加了註解相關資訊:
AnnotationMetadata getMetadata();
MethodMetadata getFactoryMethodMetadata();
ClassMetadata介面,是通過類註冊時,和類相關的一些資訊:
String getClassName();
boolean isInterface();
boolean isAnnotation();
boolean isAbstract();
boolean isConcrete();
boolean isFinal();
boolean isIndependent();
boolean hasEnclosingClass();
String getEnclosingClassName();
boolean hasSuperClass();
String getSuperClassName();
String[] getInterfaceNames();
String[] getMemberClassNames();
MethodMetadata介面,是通過工廠方法註冊時,和方法相關的資訊:
String getMethodName();
String getDeclaringClassName();
String getReturnTypeName();
boolean isAbstract();
boolean isStatic();
boolean isFinal();
boolean isOverridable();
AnnotatedTypeMetadata介面,用於獲取註解的屬性資訊:
boolean isAnnotated(String annotationName);
Map<String, Object> getAnnotationAttributes(String annotationName);
Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString);
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName);
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
AnnotationMetadata介面,用於獲取一個類上標有的註解資訊:
Set<String> getAnnotationTypes();
Set<String> getMetaAnnotationTypes(String annotationName);
boolean hasAnnotation(String annotationName);
boolean hasMetaAnnotation(String metaAnnotationName);
boolean hasAnnotatedMethods(String annotationName);
Set<MethodMetadata> getAnnotatedMethods(String annotationName);
一個小示例
上面的東西太抽象了,下面通過一個簡單的示例,來具體看下。
使用@Component註解註冊一個Boss類的bean定義。
@Component
public class Boss {
}
使用@Configuration類裡的@Bean方法註冊兩個Staff的bean定義,同時Company類的bean定義也會被註冊。
public class Staff {
}
@Configuration
public class Company {
@Bean
public Staff littleMing() {
return new Staff();
}
@Bean
public Staff littleQiang() {
return new Staff();
}
}
在註冊bean定義時,需要一個bean名稱,預設會自動生成,就是首字母小寫的類名或方法名。
因此,以上四個bean定義的名稱分別是:
boss
company
littleMing
littleQiang
既然已經到這裡了,就應該滿足一下好奇心,取出bean定義看看,是什麼樣子。
下面是Boss類的bean定義:
相關推薦
品Spring:帝國的基石
序生活是一杯酒,有時需要麻醉自己,才能夠暫時忘卻痛苦與不快。生活是一杯茶,有時需要細細品味,才發現苦澀背後也會有甘甜。Spring是一杯酒,一眼望不到邊的官方文件,著實讓人難以下嚥。Spring是一杯茶,在無邊的原始碼中暢遊之後,發現色相味道俱全。高考狀元是六月份的網紅,Spring帝國是Java界的明星。狀
品Spring:bean定義上梁山
認真閱讀,收穫滿滿,向智慧又邁進一步。。。技術不枯燥,先來點閒聊先說點好事高興一下。前段時間看新聞說,我國正式的空間站建設已在進行當中。下半年,長征五號B運載火箭將在海南文昌航天發射場擇機將空間站核心艙發射升空。預計用2到3年將空間站建好。雖然到時你們不讓我上去,不過我也為這件事出不了什麼力,算扯平了。哈哈,
品Spring:實現bean定義時採用的“先進生產力”
前景回顧當我們把寫好的業務程式碼交給Spring之後,Spring都會做些什麼呢?仔細想象一下,再稍微抽象一下,Spring所做的幾乎全部都是:“bean的例項化,bean的依賴裝配,bean的初始化,bean的方法呼叫,bean的銷燬回收”。那問題來了,Spring為什麼能夠準確無誤
品Spring:能工巧匠們對註解的“加持”
問題的描述與方案的提出在Spring從XML轉向註解時,為了自身的開發方便,對註解含義進行了擴充(具體參考本號上一篇文章)。這個擴充直接導致了一個問題,就是需要從註解往元註解以及元元註解(即沿著從下向上的方向)裡傳遞資料。為了更好的描述這個問題,請再看個示例:@interface A {&
品Spring:SpringBoot和Spring到底有沒有本質的不同?
現在的Spring相關開發都是基於SpringBoot的。最後在打包時可以把所有依賴的jar包都打進去,構成一個獨立的可執行的jar包。如下圖13: 使用java -jar命令就可以執行這個獨立的jar包。如下圖14: 這個jar包的執行入口就是一個main函式,典型的格式如下: @Spri
品Spring:負責bean定義註冊的兩個“排頭兵”
別看Spring現在玩的這麼花,其實它的“籌碼”就兩個,“容器”和“bean定義”。只有先把bean定義註冊到容器裡,後續的一切可能才有可能成為可能。所以在進階的路上如果要想走的順暢些,徹底搞清楚bean定義註冊的所有細節至關重要。畢竟這
品Spring:SpringBoot輕鬆取勝bean定義註冊的“第一階段”
上一篇文章強調了bean定義註冊佔Spring應用的半壁江山。而且詳細介紹了兩個重量級的註冊bean定義的類。今天就以SpringBoot為例,來看看整個SpringBoot應用的bean定義是如何註冊進容器的。先來看看經典的啟動入口,如下圖01: 可以看到呼叫的是run方法,並把主類(main或pr
品Spring:SpringBoot發起bean定義註冊的“二次攻堅戰”
上一篇文章整體非常輕鬆,因為在容器啟動前,只註冊了一個bean定義,就是SpringBoot的主類。OK,今天接著從容器的啟動入手,找出剩餘所有的bean定義的註冊過程。具體細節肯定會頗為複雜,同樣,大家只需關注都幹了什麼,不用考慮如何幹的。來巨集觀的看下容器的啟動過程,即refresh方法,如下圖01:
品Spring:註解之王@Configuration和它的一眾“小弟們”
其實對Spring的瞭解達到一定程度後,你就會發現,無論是使用Spring框架開發的應用,還是Spring框架本身的開發都是圍繞著註解構建起來的。空口無憑,那就說個最普通的例子吧。在Spring中要啟用一項XXX功能,標準做法就是用@EnableXXX這種“啟用”型別的註解。那麼這種型
品Spring:bean工廠後處理器的呼叫規則
上一篇文章介紹了對@Configuration類的處理邏輯,這些邏輯都寫在ConfigurationClassPostProcessor類中。 這個類不僅是一個“bean工廠後處理器”,還是一個“bean定義註冊後處理器”。這其實是兩個介面,它們都是來操作be
品Spring:詳細解說bean後處理器
一個小小的里程碑首先感謝能看到本文的朋友,感謝你的一路陪伴。如果每篇都認真看的話,會發現本系列以bean定義作為切入點,先是詳細解說了什麼是bean定義,接著又強調了bean定義為什麼如此重要。然後又講了獲取bean定義詳細資訊的方法,接著又講了bean定義註冊的若干種方式,然後是bean定義註冊方式的實現細
品Spring:對@PostConstruct和@PreDestroy註解的處理方法
在bean的例項化過程中,也會用到一系列的相關注解。如@PostConstruct和@PreDestroy用來標記初始化和銷燬方法。平常更多的是側重於應用,很少會有人去了解它背後發生的事情。今天就來看下它們的原始碼,這樣它們對你來說就不再是黑盒子了,而且學習原始碼對每個技術人來說都是必經之路。人們對事物的認知
品Spring:對@Resource註解的處理方法
@Resource是Java的註解,表示一個資源,它具有雙向的含義,一個是從外部獲取一個資源,一個是向外部提供一個資源。這其實就對應於Spring的注入和註冊。當它用在欄位和方法上時,表示前者。當它用在類上時表示後者。Spring只提供了對前者的支援。該註解本身表示的是資源,資源的含義是很寬泛的。由於絕大部分
品Spring:對@Autowired和@Value註解的處理方法
在Spring中能夠完成依賴注入的註解有JavaSE提供的@Resource註解,就是上一篇文章介紹的。還有JavaEE提供的@javax.inject.Inject註解,這個用的很少,因為一般都不會去引用JavaEE的jar包。程式設計新說注:JavaEE早已經被Oracle拋棄了。JavaEE這個名字已經
品Spring:真沒想到,三十步才能完成一個bean例項的建立
在容器啟動快完成時,會把所有的單例bean進行例項化,也可以叫做預先例項化。這樣做的好處之一是,可以及早地發現問題,及早的丟擲異常,及早地解決掉。本文就來看下整個的例項化過程。其實還是比較繁瑣的。一、從容器中找出所有的bean定義名稱因為不知道誰是單例bean,所以只能先全部找出來。如下圖01: 二、
品Spring:關於@Scheduled定時任務的思考與探索,結果尷尬了
非Spring風格的程式碼與Spring的結合現在的開發都是基於Spring的,所有的依賴都有Spring管理,這沒有問題。但是要突然寫一些非Spring風格的程式碼時,可能會很不習慣,如果還要和Spring風格的程式碼結合起來的話,就會稍顯麻煩。因為非Spring風格的程式碼不由Spring管理,所以Spr
Spring:jar包詳解
bsp bject 表達 title node unit 調度 緩存 support org.springframework.aop ——Spring的面向切面編程,提供AOP(面向切面編程)的實現 org.springframework.asm——spring 2.
Spring:使用Spring AOP時,如何獲取目標方法上的註解
cati 相關操作 config 使用 ide bject poi 註解 except 當使用spring AOP時,判斷目標方法上的註解進行相關操作,如緩存,認證權限等 自定義註解 package com.agent.annotation; import ja
1. Spring:入門
1. Spring:入門 Spring是控制反轉(IOC)和麵向切面(AOP)框架 優點: 低侵入式的 DI有效降低耦合 AOP集中管理 ORM和DAO簡化對資料庫的訪問 核心模組 核心容器: 工廠
5. Spring:簡化Spring XML配置
5. Spring:簡化Spring XML配置 總覽 自動裝配Bean的屬性 有助於減少和消除property,constructor argument等元素 基於註解的配置