本文主要介紹 Spring 原始碼中使用到的一些核心類
BeanDefinition表示Bean定義,BeanDefinition 中存在很多屬性用來描述一個Bean的特點。比如:
在Spring中,我們經常會通過以下幾種方式來定義Bean:
這些,我們可以稱之申明式定義Bean。
我們還可以程式設計式定義Bean,那就是直接通過BeanDefinition,比如:
接下來,我們來介紹幾種在Spring原始碼中所提供的BeanDefinition讀取器(BeanDefinitionReader),這些BeanDefinitionReader在我們使用Spring時用得少,但在Spring原始碼中用得多,相當於Spring原始碼的基礎設施。
AnnotatedBeanDefinitionReader
BeanDefinition 讀取器,可以直接把某個類轉換為BeanDefinition,並且會解析該類上的註解,比如:
注意:它能解析的註解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description
XmlBeanDefinitionReader
可以解析
ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner是掃描器,但是它的作用和BeanDefinitionReader類似,它可以進行掃描,掃描某個包路徑,對掃描到的類進行解析,比如,掃描到的類上如果存在@Component註解,那麼就會把這個類解析為一個BeanDefinition,比如:
BeanFactory表示Bean工廠,所以很明顯,BeanFactory會負責建立Bean,並且提供獲取Bean的APl。\
而 ApplicationContext 是 BeanFactory 的一種,在 Spring 中的定義如下
首先,在Java中,介面是可以多繼承的,我們發現ApplicationContext繼承了ListableBeanFactory和HierarchicalBeanFactory,而ListableBeanFactory和HierarchicalBeanFactory都繼承至BeanFactory,所以我們可以認為ApplicationContext繼承了BeanFactory,相當於蘋果繼承水果,寶馬繼承汽車一樣,ApplicationContext也是BeanFactory的一種,擁有BeanFactory支援的所有功能,不過ApplicationContext比BeanFactory更加強大,ApplicationContext還基礎了其他介面,也就表示ApplicationContext還擁有其他功能,比如MessageSource表示國際化,ApplicationEventPublisher表示事件釋出,EnvironmentCapable表示獲取環境變數,等等,關於ApplicationContext後面再詳細討論。
在Spring的原始碼實現中,當我們new一個ApplicationContext時,其底層會new一個BeanFactory出來,當使用ApplicationContext的某些方法時,比如getBean0,底層呼叫的是BeanFactory的getBean()方法。
在Spring原始碼中,BeanFactory介面存在一個非常重要的實現類是:DefaultListableBeanFactory,也是非常核心的。
DefaultListableBeanFactory是非常強大的,支援很多功能,可以通過檢視 DefaultListableBeanFactory的類繼承實現結構來看
上面有分析到,ApplicationContext是個介面,實際上也是一個BeanFactory,不過比BeanFactory更加強大,比如:
1.HierarchicalBeanFactory:擁有獲取父BeanFactory的功能
2.ListableBeanFactory:擁有獲取beanNames的功能3.ResourcePatternResolver:資源載入器,可以一次性獲取多個資源(檔案資源等等)
4.EnvironmentCapable:可以獲取執行時環境(沒有設定執行時環境功能)
5.ApplicationEventPublisher:擁有廣播事件的功能(沒有新增事件監聽器的功能)
6.MessageSource:擁有國際化功能
ApplicationContext 有兩個比較重要的實現類:
1.AnnotationConfig ApplicationContext
2.ClassPathXmlApplicationContext
它也是繼承了AbstractApplicationContext,但是相對於AnnotationConfigApplicationContext而言,功能沒有AnnotationConfig ApplicationContext強大,比如不能註冊BeanDefinition
BeanPostProcess表示Bena的後置處理器,我們可以定義一個或多個BeanPostProcessor,比如通過一下程式碼定義一個BeanPostProcessor:
一個BeanPostProcessor可以在任意一個Bean的初始化之前以及初始化之後去額外的做一些使用者自定義的邏輯,當然,我們可以通過判斷beanName來進行鍼對性處理(針對某個Bean,或某部分Bean)。
我們可以通過定義BeanPostProcessor來干涉Spring建立Bean的過程。
BeanFactoryPostProcessor表示Bean工廠的後置處理器,其實和BeanPostProcessor類似,BeanPostProcessor是干涉Bean的建立過程,BeanFactoryPostProcessor是干涉BeanFactory的建立過程。
上面提到,我們可以通過BeanPostPorcessor來干涉Spring建立Bean的過程,但是如果我們想一個Bean完完全全由我們來創造,也是可以的,比如通過FactoryBean:
通過上面這段程式碼,我們自己創造了一個UserService物件,並且它將成為Bean。但是通過這種方式創造出來的UserService的Bean,只會經過初始化後,其他Spring的生命週期步驟是不會經過的,比如依賴注入。
有同學可能會想到,通過@Bean也可以自己生成一個物件作為Bean,那麼和FactoryBean的區別是什麼呢?其實在很多場景下他倆是可以替換的,但是站在原理層面來說的,區別很明顯,@Bean定義的Bean是會經過完整的Bean生命週期的。
這兩個Filter是Spring掃描過程中用來過濾的。ExcludeFilter表示排除過濾器,IncludeFilter表示包含過濾器。
比如以下設定,表示掃描com.zhouyu這個包下面的所有類,但是排除UserService類,也就是就算它上面有@Component註解也不會成為Bean。
再比如以下設定,就算UserService類上沒有@Component註解,它也會被掃描成為一個Bean。
FilterType分為:
1.ANNOTATION:表示是否包含某個註解
2.ASSIGNABLE TYPE:表示是否是某個類
3.ASPECTJ:表示否是符合某個Aspectj表示式
4.REGEX:表示是否符合某個正規表示式
5.CUSTOM:自定義
在Spring的掃描邏輯中,預設會新增一個Annotation TypeFilter給includeFilters,表示預設情況下Spring掃描過程中會認為類上有@Component註解的就是Bean。
在Spring中需要去解析類的資訊,比如類名、類中的方法、類上的註解,這些都可以稱之為類的後設資料,所以Spring中對類的後設資料做了抽象,並提供了一些工具類。
MetadataReader表示類的後設資料讀取器,預設實現類為SimpleMetadataReader
需要注意的是,SimpleMetadataReader去解析類時,使用的ASM技術。
為什麼要使用ASM技術,Spring啟動的時候需要去掃描,如果指定的包路徑比較寬泛,那麼掃描的類是非常多的,那如果在Spring啟動時就把這些類全部載入進JVM了,這樣不太好,所以使用了ASM技術。