Spring @Component註解
1.概述
在本教程中,我們將全面介紹Spring @Component
批註和相關區域。到最後,我們將看到使用它與某些Spring核心功能集成的不同方法,以及如何利用其許多優點。
2. Spring ApplicationContext
在我們了解@Component
的值之前,我們必須首先了解一些有關Spring ApplicationContext
。在這裡,Spring會保存已確定要自動管理和分發的對象的實例。這些被稱為豆。 Bean管理和依賴注入的機會是Spring的一些主要功能。
使用“控制反轉”原理, Spring從我們的應用程序中收集bean實例,並在適當的時間使用它們。我們可以顯示對Spring的bean依賴關係,而無需處理那些對象的設置和實例化。
使用@Autowired
註釋將Spring託管的bean注入我們的應用程序的能力是在Spring中創建功能強大且可伸縮的代碼的驅動力。
那麼,我們如何告訴Spring我們希望它為我們管理的bean?我們應該通過在類上使用構造型註釋來利用Spring的自動bean檢測功能。
3. @Component
@Component
是一個註釋,它允許Spring自動檢測我們的自定義bean。
換句話說,無需編寫任何顯式代碼,Spring即可:
- 掃描我們的應用程序以查找帶有
@Component
- 實例化它們並將任何指定的依賴項注入到它們中
- 隨時隨地註入
但是,大多數開發人員更喜歡使用更專業的構造型註釋來實現此功能。
3.1。Spring 其他註解
Spring提供了一些專門的@Controller
, @Service
Service和@Repository
。它們都提供與@Component
相同的功能。它們都具有相同作用的原因是它們都是由@Component
作為每個註釋的元註釋組成的註釋。它們就像@Component
別名,具有特殊用途,並且在Spring自動檢測或依賴項注入之外具有含義。
如果確實需要,從理論上講,我們可以選擇@Component
來滿足我們的bean自動檢測需求。另一方面,我們也可以使用@Component
自己的專用註釋。但是,Spring的其他領域專門針對Spring的特殊註釋,以提供額外的自動化好處。因此,我們可能大多數時候都應該堅持使用已建立的專業。
假設我們在Spring Boot項目中有每種情況的示例:
@Controller
public class ControllerExample {
}
@Service
public class ServiceExample {
}
@Repository
public class RepositoryExample {
}
@Component
public class ComponentExample {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface CustomComponent {
}
@CustomComponent
public class CustomComponentExample {
}
我們可以編寫一個測試來證明Spring會自動檢測到每個測試並將其添加到ApplicationContext
:
@SpringBootTest
@ExtendWith(SpringExtension.class)
public class ComponentUnitTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void givenInScopeComponents_whenSearchingInApplicationContext_thenFindThem() {
assertNotNull(applicationContext.getBean(ControllerExample.class));
assertNotNull(applicationContext.getBean(ServiceExample.class));
assertNotNull(applicationContext.getBean(RepositoryExample.class));
assertNotNull(applicationContext.getBean(ComponentExample.class));
assertNotNull(applicationContext.getBean(CustomComponentExample.class));
}
}
3.2。 @ComponentScan
在我們完全依賴@Component
之前,我們必須了解一下,它本身只是一個簡單的註釋。註釋用於將bean與其他對象(例如域對象)區分開的目的。但是, Spring使用@ComponentScan
批註將它們全部收集到其ApplicationContext
。
如果我們正在編寫Spring Boot應用程序,那麼了解@SpringBootApplication
是一個包含@ComponentScan
的組合批註會很有幫助。只要我們的@SpringBootApplication
類位於項目的根目錄下,它將掃描默認情況下定義的@Component
但是,如果我們的@SpringBootApplication
類不能位於項目的根目錄下,或者我們想掃描外部源,則可以@ComponentScan
以查找我們指定的任何包,只要它存在於類路徑中即可。
讓我們定義一個範圍外的@Component
bean:
package com.baeldung.component.scannedscope;
@Component
public class ScannedScopeExample {
}
接下來,我們可以通過對@ComponentScan
批註的明確說明將其包括在內:
package com.baeldung.component.inscope;
@SpringBootApplication
@ComponentScan({"com.baeldung.component.inscope", "com.baeldung.component.scannedscope"})
public class ComponentApplication {
//public static void main(String[] args) {...}
}
最後,我們可以測試它的存在:
@Test
public void givenScannedScopeComponent_whenSearchingInApplicationContext_thenFindIt() {
assertNotNull(applicationContext.getBean(ScannedScopeExample.class));
}
實際上,當我們要掃描項目中包含的外部依賴項時,更可能發生這種情況。
3.3。 @Component
限制
@Component
時,我們希望某個對象成為Spring管理的bean。
例如,讓我們在項目外部的包中@Component
package com.baeldung.component.outsidescope;
@Component
public class OutsideScopeExample {
}
這是一個證明ApplicationContext
不包含外部組件的測試:
@Test
public void givenOutsideScopeComponent_whenSearchingInApplicationContext_thenFail() {
assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(OutsideScopeExample.class));
}
另外,我們可能無法訪問源代碼,因為它來自第三方資源,並且我們無法添加@Component
批註。或者,也許我們想根據我們所運行的環境有條件地使用一種bean實現,而不是另一種。大多數情況下,自動檢測就足夠了,但是如果不是,我們可以使用@Bean
。
4. @Component
與@Bean
@Bean
也是Spring在運行時用於收集bean的註釋,但在類級別未使用。相反,我們使用@Bean
註釋方法,以便Spring可以將方法的結果存儲為Spring Bean。
要查看其工作方式的示例,首先讓我們創建一個沒有註釋的POJO:
public class BeanExample {
}
@Configuration
註釋的類中,我們可以創建一個bean生成方法:
@Bean
public BeanExample beanExample() {
return new BeanExample();
}
BeanExample
可能表示一個本地類,也可能是一個外部類。沒關係,因為我們只需要返回它的一個實例。
然後,我們可以編寫一個測試來驗證Spring是否確實拾取了bean:
@Test
public void givenBeanComponent_whenSearchingInApplicationContext_thenFindIt() {
assertNotNull(applicationContext.getBean(BeanExample.class));
}
@Component
和@Bean
之間的差異,我們應該注意一些重要的含義。
-
@Component
是類級別的註釋,但是@Bean
是方法級別的,因此@Component
僅在類的源代碼可編輯時才是一個選項。@Bean
總是可以使用,但是更冗長。 -
@Component
與Spring的自動檢測兼容,但是@Bean
需要手動的類實例化。 - 使用
@Bean
將Bean的實例與其類定義解耦。這就是為什麼我們可以使用它甚至將3rd Party類製作為Spring Bean的原因。這也意味著我們可以引入邏輯來決定要使用bean的幾個可能的實例選項中的哪一個。
5.結論
我們剛剛探討了Spring @Component
批註以及其他相關主題。首先,我們討論了各種Spring構造型註解,它們只是@Component
專門版本。然後,我們了解到@Component
不會執行任何操作,除非@ComponentScan
可以找到它。最後,由於無法@Component
上使用@Component,因此我們學習瞭如何使用@Bean
註解。