Spring 核心概念

2022-07-10 15:01:29

Spring 核心概念

引言

本文主要介紹 Spring 原始碼中使用到的一些核心類

1. BeanDefinition

BeanDefinition表示Bean定義,BeanDefinition 中存在很多屬性用來描述一個Bean的特點。比如:

  • class,表示Bean型別
  • scope,表示Bean作用域,單例或原型等
  • lazylnit:表示Bean是否是懶載入
  • initMethodName:表示Bean初始化時要執行的方法
  • destroyMethodName:表示Bean銷燬時要執行的方法
  • 還有很多。。。

在Spring中,我們經常會通過以下幾種方式來定義Bean:

  1. bean 標籤
  2. @Bean
  3. @Component(@Service,@Controller)

這些,我們可以稱之申明式定義Bean。
我們還可以程式設計式定義Bean,那就是直接通過BeanDefinition,比如:

2. BeanDefinitionReader

接下來,我們來介紹幾種在Spring原始碼中所提供的BeanDefinition讀取器(BeanDefinitionReader),這些BeanDefinitionReader在我們使用Spring時用得少,但在Spring原始碼中用得多,相當於Spring原始碼的基礎設施。

AnnotatedBeanDefinitionReader

BeanDefinition 讀取器,可以直接把某個類轉換為BeanDefinition,並且會解析該類上的註解,比如:

注意:它能解析的註解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description

XmlBeanDefinitionReader

可以解析標籤,將 xml 檔案中定義的 bean 解析為 BeanDefinition

ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner是掃描器,但是它的作用和BeanDefinitionReader類似,它可以進行掃描,掃描某個包路徑,對掃描到的類進行解析,比如,掃描到的類上如果存在@Component註解,那麼就會把這個類解析為一個BeanDefinition,比如:

3. BeanFactory

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的類繼承實現結構來看

4. ApplicationContext

上面有分析到,ApplicationContext是個介面,實際上也是一個BeanFactory,不過比BeanFactory更加強大,比如:
1.HierarchicalBeanFactory:擁有獲取父BeanFactory的功能
2.ListableBeanFactory:擁有獲取beanNames的功能3.ResourcePatternResolver:資源載入器,可以一次性獲取多個資源(檔案資源等等)
4.EnvironmentCapable:可以獲取執行時環境(沒有設定執行時環境功能)
5.ApplicationEventPublisher:擁有廣播事件的功能(沒有新增事件監聽器的功能)
6.MessageSource:擁有國際化功能

ApplicationContext 有兩個比較重要的實現類:

1.AnnotationConfig ApplicationContext
2.ClassPathXmlApplicationContext

4.1 AnnotationConfig ApplicationContext

  1. ConfigurableApplicationContext:繼承了ApplicationContext介面,增加了,新增事件監聽器、新增BeanFactoryPostProcessor、設定Environment,獲取ConfigurableListableBeanFactory等功能
  2. AbstractApplicationContext:實現了ConfigurableApplicationContext介面
  3. GenericApplicationContext:繼承了AbstractApplicationContext,實現了BeanDefinitionRegistry介面,擁有了所有ApplicationContext的功能,並且可以註冊BeanDefinition,注意這個類中有一個屬性(DefaultListableBeanFactory beanFactory)
  4. AnnotationConfigRegistry:可以單獨註冊某個為類為BeanDefinition(可以處理該類上的
    @Configuration註解,已經可以處理@Bean註解),同時可以掃描
  5. AnnotationConfig ApplicationContext:繼承了GenericApplicationContext,實現了AnnotationConfigRegistry介面,擁有了以上所有的功能

4.2 ClassPathXmlApplicationContext

它也是繼承了AbstractApplicationContext,但是相對於AnnotationConfigApplicationContext而言,功能沒有AnnotationConfig ApplicationContext強大,比如不能註冊BeanDefinition

5. BeanPostProcessor

BeanPostProcess表示Bena的後置處理器,我們可以定義一個或多個BeanPostProcessor,比如通過一下程式碼定義一個BeanPostProcessor:

一個BeanPostProcessor可以在任意一個Bean的初始化之前以及初始化之後去額外的做一些使用者自定義的邏輯,當然,我們可以通過判斷beanName來進行鍼對性處理(針對某個Bean,或某部分Bean)。
我們可以通過定義BeanPostProcessor來干涉Spring建立Bean的過程。

6. BeanFactoryPostProcessor

BeanFactoryPostProcessor表示Bean工廠的後置處理器,其實和BeanPostProcessor類似,BeanPostProcessor是干涉Bean的建立過程,BeanFactoryPostProcessor是干涉BeanFactory的建立過程。

7. FactoryBean

上面提到,我們可以通過BeanPostPorcessor來干涉Spring建立Bean的過程,但是如果我們想一個Bean完完全全由我們來創造,也是可以的,比如通過FactoryBean:

通過上面這段程式碼,我們自己創造了一個UserService物件,並且它將成為Bean。但是通過這種方式創造出來的UserService的Bean,只會經過初始化後,其他Spring的生命週期步驟是不會經過的,比如依賴注入。
有同學可能會想到,通過@Bean也可以自己生成一個物件作為Bean,那麼和FactoryBean的區別是什麼呢?其實在很多場景下他倆是可以替換的,但是站在原理層面來說的,區別很明顯,@Bean定義的Bean是會經過完整的Bean生命週期的。

8.ExcludeFilter和IncludeFilter

這兩個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。

9. MetadataReader、ClassMetadata、Annotation Metadata

在Spring中需要去解析類的資訊,比如類名、類中的方法、類上的註解,這些都可以稱之為類的後設資料,所以Spring中對類的後設資料做了抽象,並提供了一些工具類。
MetadataReader表示類的後設資料讀取器,預設實現類為SimpleMetadataReader

需要注意的是,SimpleMetadataReader去解析類時,使用的ASM技術。
為什麼要使用ASM技術,Spring啟動的時候需要去掃描,如果指定的包路徑比較寬泛,那麼掃描的類是非常多的,那如果在Spring啟動時就把這些類全部載入進JVM了,這樣不太好,所以使用了ASM技術。