Spring bean詳細介紹
簡而言之,Spring bean是Spring框架在執行時管理的物件。Spring bean是任何Spring應用程式的基本構建塊。您編寫的大多數應用程式邏輯程式碼都將放在Spring bean中。
Spring bean的管理包括:
- 建立一個物件
- 提供依賴項(例如其他bean,配置屬性)
- 攔截物件方法呼叫以提供額外的框架功能
- 銷燬一個物件
Spring bean是框架的基本概念。作為Spring的使用者,您應該對這個核心抽象有深刻的理解。
如何定義Spring bean?
如您所知,Spring負責建立bean物件。但首先,您需要告訴框架它應該建立哪些物件。
你是怎麼做到的?
透過提供bean定義。
Bean定義告訴Spring框架應該將哪些類用作bean。但那還不是全部。Bean定義就像食譜一樣。它們還描述了bean的屬性。我們將在本文後面討論屬性。但在我們進入之前,讓我們關注bean的定義。
您可以透過三種不同的方式定義Spring bean:
- 使用構造型@Component註釋(或其衍生物)註釋您的類
- 編寫在自定義Java配置類中使用@Bean註釋的bean工廠方法
- 在XML配置檔案中宣告bean定義
在現代專案中,您將僅使用元件註釋和bean工廠方法。如果涉及到XML配置,那麼Spring現在主要允許它向後相容。
bean定義方法之間的選擇主要取決於對要用作Spring bean的類的原始碼的訪問。
Spring bean為@Component
如果您擁有原始碼,則通常會直接在類上使用@Component註釋。
@Component class MySpringBeanClass { //... } |
在執行時,Spring會找到所有使用@Component或其派生類進行註釋的類,並將它們用作bean定義。查詢帶註釋的類的過程稱為元件掃描。
您可能想知道@Component的衍生物是什麼。
@Conpontent衍生物是Spring構造型註釋,它們本身用@Component註釋。這個事實允許我們用它們代替@Component。
@Component衍生列表包括:
- @Service
- @Repository
- @Controller
註釋之間的區別純粹是資訊性的。它們允許您根據通用職責輕鬆對bean進行分類。您可以使用這些註釋將bean類標記為特定應用程式層的成員,Spring框架會將它們全部視為@Components。
使用@Bean作為工廠方法
如果某個類屬於某個外部庫而您無法使用@Component進行註釋,您必須在自定義bean的配置類中使用@ Bean註釋建立工廠方法。如果您不想使類依賴於Spring,您也可以將此選項用於您擁有的類。
這是一個帶有單個bean工廠方法的示例配置類:
@Configuration class MyConfigurationClass { @Bean public NotMyClass notMyClass() { return new NotMyClass(); } } |
Spring使用工廠方法在執行時建立實際物件。如您所見,該方法只返回一個類的新例項。如果某個類屬於某個外部庫而您無法使用@Component進行註釋,則使用@Bean建立工廠方法是唯一的選擇。
@Configuration註釋也來自Spring。實際上,它是@Component的衍生物,但具有特殊用途。註釋將類標記為@Bean定義的容器。您可以在單個配置類中編寫多個工廠方法。
Spring bean屬性
此時,您已經知道如何將類標記為Spring bean。下一步是學習如何自定義bean的功能。
無論您選擇哪種bean定義方法,它們都允許描述同一組bean屬性。屬性提供有關Spring應如何建立物件的詳細資訊。
Spring bean屬性列表包括:
- 類
- 名稱
- 依賴
- 範圍
- 初始化模式
- 初始化回撥
- 破壞回撥
為了簡化bean定義,Spring為幾乎所有屬性提供了預設值。但是,瞭解如何自定義預設值非常重要。讓我們逐個研究Spring bean屬性。
1.Bean類
建立bean定義時,將其與應用程式中的單個具體類連線。這個類本身是bean的主要屬性。
當Spring查詢依賴項時,class屬性是bean的預設識別符號。這是否意味著您不能為單個類提供多個bean定義?不,這是可能的。但在這種情況下,為避免歧義,您應該使用另一個bean識別符號:一個name名稱。
2. Bean名稱name
Spring bean名稱是Spring用於標識bean的自定義字串。與bean類不同,名稱在整個應用程式中必須是唯一的。您不能定義兩個具有相同名稱的bean,即使它們的型別不同。
幸運的是,您不必為您建立的每個bean設定名稱。Spring在執行時為其內部使用生成名稱。除非您想按名稱識別bean,否則可以安全地使用預設設定。
您需要使用bean名稱的主要情況是為使用@Bean批註定義的同一個類提供了幾個bean。在這種情況下,名稱允許您標識要用作另一個bean的依賴項的特定例項。
3. 如何命名Spring bean?
使用@Bean批註的name屬性。這是兩個具有相同型別的bean的示例。
@Configuration class MyConfigurationClass { @Bean(name = "myBeanClass") MyBeanClass myBeanClass() { return new MyBeanClass(); } @Bean(name = "anotherMyBeanClass") MyBeanClass anotherMyBeanClass() { return new MyBeanClass(); } } |
實際上,您不經常定義bean名稱。對於單個類具有多個bean是相當罕見的情況。然而,如果能瞭解命名bean的各種可能性也是不錯的。
4. Bean依賴項
用作bean的物件可以使用其他bean來執行其作業。當Spring建立一個定義某些依賴項的物件時,框架需要首先建立這些依賴項。這些依賴項也可以有自己的依賴項。
在物件導向的應用程式中,我們通常使用相關物件的巨大圖表。幸運的是,我們不必考慮如何構建此圖。我們不必考慮應該建立物件的順序。Spring為我們做了所有這些。
Spring對您的唯一期望是特定bean的依賴項列表。
5.如何定義bean依賴?
Bean依賴關係定義是一個複雜的主題,值得單獨一篇文章。請考慮以下段落作為該主題的介紹。
當你有一個用@Component標記的類並且只有一個建構函式時,Spring使用建構函式引數列表作為必需依賴項列表。預設情況下,框架使用建構函式引數型別來提供適當的物件。
@Component class BeanWithDependency { private final MyBeanClass beanClass; BeanWithDependency(MyBeanClass beanClass) { this.beanClass = beanClass; } } |
過去,我們在建構函式上使用@Autowired註釋。但是,從Spring 4.3開始,如果只有一個建構函式,則不是強制性的。但是,如果bean類定義了多個建構函式,則應使用@Autowired標記一個。這樣Spring知道哪個建構函式包含bean依賴項列表。
出於同樣的原因,bean工廠方法可以定義其依賴關係。Spring使用適當的物件呼叫方法。
@Bean BeanWithDependency beanWithOptionalDependency(MyBeanClass beanClass) { return new BeanWithDependency(beanClass); } |
6. Bean作用域
Spring bean的範圍定義了框架在執行時建立的特定類的例項數。作用域還描述了建立新物件的條件。
Spring為您的bean提供了幾個作用域。框架的核心有兩個:
- 單例 - 單個例項
- 原型 - 多個例項
此外,Spring還附帶了專門用於Web應用程式的bean作用域:
- 請求
- 會話
- 全域性會話
- 應用級別Application
所有bean的預設作用域是單例。當bean具有單例作用域時,Spring只建立一個例項並在整個應用程式中共享它。單例是無狀態物件的完美選擇。如今,我們應用程式中的絕大多數bean都是無狀態單例。
另一方面,如果物件包含狀態,則應考慮其他作用域。要選擇正確的一個,您應該問自己框架應該將該狀態保留在記憶體中多長時間。但這是另一篇文章。
7. 如何設定作用域?
無論是使用@Component直接註釋類還是使用@Bean建立工廠方法,該方法都是相同的。使用@Scope批註及其字串屬性選擇範圍。
@Component @Scope("prototype") class MyPrototypeClass { //... } @Bean @Scope("prototype") MyPrototypeClass myPrototypeClass() { return new MyPrototypeClass(); } |
更重要的是,對於Web作用域,Spring附帶了額外的別名註釋。您可以使用這些註釋代替@Scope:
- @RequestScope
- @SessionScope
- @ApplicationScope
Bean初始化模式
當您的應用程式啟動時,Spring會在啟動時會立即建立所有單例bean。此預設行為允許我們快速檢測bean定義中的錯誤。另一方面,立即性eager bean初始化會使應用程式的啟動變慢。
幸運的是,您可以將bean的建立延遲到實際需要的時刻。您可以使用@Lazy註釋執行此操作。
@Component @Lazy class MyLazyClass { //... } |
Bean初始化回撥
一旦Spring根據bean定義建立新例項,您可能希望執行一些物件初始化邏輯。
如果此邏輯不依賴於框架,則可以在物件的建構函式中執行它。但是,為了確保在Spring初始化物件之後執行邏輯(例如,在可選的依賴注入之後),您應該使用初始化回撥。
如何設定bean初始化回撥?
如果使用@Component定義bean ,則有兩個選項:
- 使bean類實現InitializingBean。介面將強制您實現初始化方法。
- 編寫自定義初始化方法並使用javax @PostContruct註釋進行標記。
在這兩種情況下,Spring都會為您執行初始化回撥。
用工廠方法定義的bean怎麼樣?
您可以使用@Bean及其名為initMethod的屬性設定初始化回撥。該屬性需要一個具有初始化方法名稱的字串。
@Bean(initMethod = "someInitMethodName") MySpringBeanClass meBeanClass() { return new MySpringBeanClass(); } |
有趣的是,用作初始化回撥的方法可以具有私有訪問控制。Spring使用反射機制來呼叫該方法。
Bean銷燬回撥
與初始化回撥類似,您可以定義Spring銷燬bean時應呼叫的方法。Predestroy回撥的使用要少得多,但要注意它們的存在是很好的。
如何設定bean銷燬回撥?
同樣,如果您可以訪問bean類的原始碼,則可以使用以下兩個選項之一:
- 實現DisposableBean介面。Spring使用其唯一的方法進行銷燬回撥。
- 編寫自定義方法並使用Javax API中的@PreDestroy註釋它。
對於工廠方法,使用@Bean批註及其destroyMethod屬性。
@Bean(name = "myBeanClass", destroyMethod = "cleanUpMethod") MySpringBeanClass meBeanClass() { return new MySpringBeanClass(); } |
Spring如何從bean定義建立物件?
當您啟動Spring應用程式時,框架首先會建立一個名為ApplicationContext的特殊物件。ApplicationContext,也稱為控制反轉(IoC)容器,是框架的核心。
ApplicationContext是存在bean物件的容器。
上下文負責檢測和讀取Spring bean定義。一旦ApplicationContext載入了bean定義,它就可以根據提供的bean屬性及其依賴關係開始為應用程式建立bean物件。
相關文章
- Spring原始碼系列(一)--詳細介紹bean元件Spring原始碼Bean元件
- spring @component 的作用詳細介紹Spring
- javascript this詳細介紹JavaScript
- JDBC 詳細介紹JDBC
- Kafka詳細介紹Kafka
- Git詳細介紹Git
- Spring配置bean的詳細知識SpringBean
- Go Channel 詳細介紹Go
- Nacos 介面詳細介紹
- MQ詳細命令介紹MQ
- Recovery命令詳細介紹
- Vmstat 命令詳細介紹
- Flutter系列(一)——詳細介紹Flutter
- Nginx服務詳細介紹Nginx
- python字典詳細介紹Python
- Http Module 的詳細介紹HTTP
- Java異常詳細介紹Java
- 【SCN】Oracle SCN 詳細介紹Oracle
- SOLIDWORKS API詳細介紹SolidAPI
- Webpack 打包 Javascript 詳細介紹WebJavaScript
- mysql binlog詳細介紹MySql
- java泛型詳細介紹Java泛型
- 【工具】Sublime使用詳細介紹
- asmcmd工具的詳細介紹ASM
- json詳細介紹(for Java)JSONJava
- Mysqldump工具的詳細介紹MySql
- rman超詳細命令介紹
- Aix 上NFS詳細介紹AINFS
- ApplicationContext 詳細介紹APPContext
- Spring中Bean的例項化詳細流程SpringBean
- 詳細介紹Spring Boot + RabbitMQ實現延遲佇列Spring BootMQ佇列
- TreeViewTemplate移動元件詳細介紹View元件
- pyhanlp 文字聚類詳細介紹HanLP聚類
- LVM詳細介紹及建立LVM
- oracle 大頁配置詳細介紹Oracle
- js中typeof用法詳細介紹JS
- 詳細介紹Linux指令odLinux
- Linux下udev詳細介紹Linuxdev