<div>
<a class="article-series-header" href="javascript:void(0);">該文章是系列中的一部分</a>
<div>
<div>
<div>
• Spring Core 註解 <span>(當前文章)</span>
</div>
• Spring Web 註解
<br>
• Spring Boot 註解
<br>
• Spring Scheduling 註解
<br>
• Spring Data 註解
<br>
• Spring Bean 註解
<br>
</div>
<!-- end of article series inner -->
</div>
<!-- .article-series-links -->
</div>
<!-- end of article series section -->
1. 概述
我們可以利用 Spring DI 引擎中的註解,通過 org.springframework.beans.factory.annotation 和 org.springframework.context.annotation 包來實現。
我們通常將這些註解稱為“Spring 核心註解”,並在本教程中進行回顧。
2. DI 相關注釋
2.1. <em @Autowired
我們可以使用 <em @Autowired> 來標記一個 Spring 將要解析並注入的依賴項。 我們可以使用此註解與構造函數、設置方法或字段注入一起使用。
構造函數注入:
class Car {
Engine engine;
@Autowired
Car(Engine engine) {
this.engine = engine;
}
}Setter 注入:
class Car {
Engine engine;
@Autowired
void setEngine(Engine engine) {
this.engine = engine;
}
}字段注入:
class Car {
@Autowired
Engine engine;
}@Autowired 具有一個 boolean 類型的參數 required,默認值為 true。它調整 Spring 的行為,當找不到合適的 Bean 進行注入時。當 true 時,會拋出異常,否則什麼也不進行注入。
注意,如果使用構造函數注入,所有構造函數參數都必須是必需的。
從 4.3 版本開始,除非我們聲明至少有兩個構造函數,否則我們無需顯式地使用 @Autowired 註解來標註構造函數。
有關更多詳細信息,請參閲我們關於 @Autowired 和構造函數注入的文章。
2.2. <em @Bean@
@Bean 標記了一個工廠方法,用於實例化一個 Spring Bean。
@Bean
Engine engine() {
return new Engine();
}Spring 在需要創建返回類型的新的實例時,會調用這些方法。
生成的 Bean 的名稱與工廠方法相同。如果希望將其命名為不同,可以使用 name 或 value 屬性(value 屬性是 name 屬性的別名)進行指定:
@Bean("engine")
Engine getEngine() {
return new Engine();
}請注意,所有帶有 @Bean 註解的方法必須位於 @Configuration 類中。
2.3. <em @Qualifier</em>
我們使用 <em @Qualifier</em> 與 <em @Autowired</em> 共同提供在歧義情況下我們想要使用的 Bean ID 或 Bean 名稱。
例如,以下兩個 Bean 實現相同的接口:
class Bike implements Vehicle {}
class Car implements Vehicle {}如果 Spring 需要注入一個 Vehicle Bean,它可能會遇到多個匹配的定義。 在這種情況下,我們可以使用 @Qualifier 註解顯式指定 Bean 的名稱。
使用構造注入:
@Autowired
Biker(@Qualifier("bike") Vehicle vehicle) {
this.vehicle = vehicle;
}使用 setter 注入:
@Autowired
void setVehicle(@Qualifier("bike") Vehicle vehicle) {
this.vehicle = vehicle;
}或者:
@Autowired
@Qualifier("bike")
void setVehicle(Vehicle vehicle) {
this.vehicle = vehicle;
}使用字段注入:
@Autowired
@Qualifier("bike")
Vehicle vehicle;欲瞭解更詳細的描述,請閲讀本文。
2.4. @Value
我們可以使用 @Value 將屬性值注入到 Bean 中。它與構造函數注入、setter 注入和字段注入兼容。
構造函數注入:
Engine(@Value("8") int cylinderCount) {
this.cylinderCount = cylinderCount;
}<p>Setter injection:</p>
@Autowired
void setCylinderCount(@Value("8") int cylinderCount) {
this.cylinderCount = cylinderCount;
}或者:
@Value("8")
void setCylinderCount(int cylinderCount) {
this.cylinderCount = cylinderCount;
}字段注入:
@Value("8")
int cylinderCount;當然,注入靜態值並非有效。因此,我們可以使用 佔位符字符串 在 @Value 中來連接來自 外部來源 的值,例如在 .properties 或 .yaml 文件中。
讓我們假設以下 .properties 文件:
engine.fuelType=petrol我們可以通過以下方式注入 engine.fuelType 的值:
@Value("${engine.fuelType}")
String fuelType;我們可以使用 @Value 甚至與 SpEL 結合使用。 更多高級示例請參考我們關於 @Value 的文章。
2.5. <em @DependsOn</em>>
我們可以使用此註解來使 Spring 在註解類執行之前初始化其他 Bean。通常,這種行為是自動的,基於 Bean 之間的顯式依賴關係。
我們只需要此註解,當依賴關係是隱式的,例如 JDBC 驅動程序加載或靜態變量初始化。
我們可以使用 <em @DependsOn</em>> 在依賴類上指定依賴 Bean 的名稱。該註解的 <em value</em> 參數需要一個包含依賴 Bean 名稱的數組:
@DependsOn("engine")
class Car implements Vehicle {}如果定義了一個帶有 @Bean 標註的 Bean,則工廠方法應使用 @DependsOn 標註:
@Bean
@DependsOn("fuel")
Engine engine() {
return new Engine();
}2.6. <em @Lazy</em>>
我們使用 <em @Lazy</em>> 當我們希望延遲初始化我們的 Bean 時。默認情況下,Spring 在應用程序上下文的啓動/構建過程中會立即創建所有單例 Bean。
然而,在某些情況下,我們需要在請求 Bean 時創建它,而不是在應用程序啓動時創建。
此註解的行為取決於我們將其放置的確切位置。我們可以將其放置在:
- 一個帶有 `>` 註解的 Bean 工廠方法上,以延遲方法調用(從而延遲 Bean 的創建)
- 一個 `` 類及其包含的所有 `>` 方法將會受到影響
- 一個不 являться `` 類的 `` 類,此 Bean 將會延遲初始化
- 一個 `` 構造函數、設置方法或字段,以延遲加載依賴項本身(通過代理)
此註解有一個名為 <em value</em> 的參數,默認值為 `<em true>。它對於覆蓋默認行為很有用。
例如,當全局設置設置為延遲時,標記 Bean 以立即加載,或者在帶有 <em @Lazy</em>> 註解的 <em @Configuration</em> 類中配置特定 <em @Bean</em>> 方法以進行立即加載:
@Configuration
@Lazy
class VehicleFactoryConfig {
@Bean
@Lazy(false)
Engine engine() {
return new Engine();
}
}欲瞭解更多信息,請訪問本文。
2.7. <em @Lookup</em>
一個帶有 `` 註解的方法,會告訴 Spring 在調用該方法時,返回該方法返回類型的實例。
關於該註解的詳細信息,請參考本文。
2.8. <em @Primary</em>>
有時我們需要定義同類型的多個Bean。在這種情況下,注入將失敗,因為Spring無法確定需要哪個Bean。
我們之前已經看到了一種處理這種情況的方法:使用<em @Qualifier</em>>標記所有注入點,並指定所需Bean的名稱。
然而,大多數情況下,我們只需要特定的Bean,而很少需要其他的。我們可以使用<em @Primary</em>>來簡化這種情況:如果我們用<em @Primary>標記最常用的Bean,它將在未限定注入點上被選中:
@Component
@Primary
class Car implements Vehicle {}
@Component
class Bike implements Vehicle {}
@Component
class Driver {
@Autowired
Vehicle vehicle;
}
@Component
class Biker {
@Autowired
@Qualifier("bike")
Vehicle vehicle;
}在之前的示例中,Car 是主要的車輛。因此,在 Driver 類中,Spring 注入了一個 Car Bean。當然,在 Biker Bean 中,字段 vehicle 的值將是一個 Bike 對象,因為它是明確指定的。
2.9. @Scope
我們使用 @Scope 來定義 @Component 類或 @Bean 聲明的範圍。它可以是 singleton, prototype, request, session, globalSession 或自定義範圍。
例如:
@Component
@Scope("prototype")
class Engine {}3. 上下文配置註釋
我們可以使用本節中描述的註釋來配置應用程序上下文。
3.1. <em @Profile@
如果希望 Spring 只在特定 profile 激活時使用 @Component 類或 @Bean 方法,我們可以使用 註解標記它們。可以使用註解的 參數配置 profile 的名稱。
@Component
@Profile("sportDay")
class Bike implements Vehicle {}您可以在這篇文章中瞭解更多關於“配置文件”的信息。
3.2. <em @Import</em>>
我們可以使用此註解,在不進行組件掃描的情況下,使用特定的 <em @Configuration</em>> 類。 通過將 <em @Import</em>> 的 <em value</em> 參數提供給這些類來實現:
@Import(VehiclePartSupplier.class)
class VehicleFactoryConfig {}3.3. <em @ImportResource</em>>
我們可以使用此註解導入 XML 配置。可以使用 <em location</em>> 參數或其別名 <em value</em>> 參數指定 XML 文件位置:
@Configuration
@ImportResource("classpath:/annotations.xml")
class VehicleFactoryConfig {}3.4. <em @PropertySource
使用此註解,我們可以定義應用程序設置的屬性文件:
@Configuration
@PropertySource("classpath:/annotations.properties")
class VehicleFactoryConfig {}@PropertySource 利用了 Java 8 的重複註解特性,這意味着我們可以用它標記一個類多次:
@Configuration
@PropertySource("classpath:/annotations.properties")
@PropertySource("classpath:/vehicle-factory.properties")
class VehicleFactoryConfig {}3.5. <em @PropertySources@
我們可以使用此註解來指定多個 <em @PropertySource@> 配置:
@Configuration
@PropertySources({
@PropertySource("classpath:/annotations.properties"),
@PropertySource("classpath:/vehicle-factory.properties")
})
class VehicleFactoryConfig {}請注意,自 Java 8 以來,我們就可以通過重複註解功能(如上文所述)來實現相同的結果。
4. 結論
在本文中,我們對 Spring 核心註解進行了概述。我們瞭解瞭如何配置 Bean 注入和應用上下文,以及如何標記類以供組件掃描。