1. 簡介
可以説,現代軟件設計中最重要的一條開發原則是依賴注入 (DI),這自然地流露出另一條至關重要的原則:模塊化。
本快速教程將探討 Spring 中一種特定類型的依賴注入技術,即基於構造函數的依賴注入,簡單來説,就是我們在實例化類時,將所需的組件傳遞過去。
為了開始,我們需要在我們的 pom.xml 中導入 spring-boot-starter-web 依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>然後我們需要設置一個 配置文件。該文件可以是POJO或XML文件,根據個人偏好而定。
2. 基於標註的配置
Java 配置文件與 Java 對象類似,但包含一些額外的標註:
@Configuration
@ComponentScan("com.baeldung.constructordi")
public class Config {
@Bean
public Engine engine() {
return new Engine("v8", 5);
}
@Bean
public Transmission transmission() {
return new Transmission("sliding");
}
}
在這裏,我們使用註釋來通知 Spring 運行時,該類提供 Bean 定義(@Bean 註解),並且 com.baeldung.spring 包需要執行上下文掃描以查找其他 Bean。接下來,我們定義一個 Car 類:
@Component
public class Car {
@Autowired
public Car(Engine engine, Transmission transmission) {
this.engine = engine;
this.transmission = transmission;
}
}Spring 在進行包掃描時會遇到 Car 類,並會通過調用帶有 @Autowired 註解的構造函數來初始化其實例。
通過調用 Config 類中的帶有 @Bean 註解的方法,我們將獲得 Engine 和 Transmission 實例。最後,我們需要使用我們的 POJO 配置來啓動 ApplicationContext 。
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
Car car = context.getBean(Car.class);3. 隱式構造器注入
擁有單個構造器的類可以省略 <em @Autowired</em> 註解。這提供了一個方便的小功能,並減少了樣板代碼。
此外,從 4.3 版本開始,我們還可以利用在 <em @Configuration</em> 註解類中的構造器注入。 另外,如果此類只有一個構造器,則也可以省略 <em @Autowired</em> 註解。
4. 優缺點
構造器注入與字段注入相比具有一些優勢。
第一個好處是可測試性。 假設我們要對使用字段注入的 Spring Bean 進行單元測試:
public class UserService {
@Autowired
private UserRepository userRepository;
}在構建 <em lang="en">UserService </em lang="en">實例時,我們無法初始化userRepository </em lang="en">狀態。唯一的途徑是通過 Reflection API 實現,這完全破壞了封裝性。並且,生成的代碼與簡單的構造器調用相比,安全性會降低。
此外,with field injection,我們無法強制類級不變性,因此有可能存在未正確初始化的 `UserService 實例。因此,我們可能會在這裏遇到隨機的 `NullPointerException 。 此外,使用構造器注入,更容易構建不可變組件。
更重要的是,使用構造器創建對象實例是 OOP 角度上更自然的做法。
另一方面,構造器注入的主要缺點是其冗餘性,尤其當一個 Bean 有幾個依賴項時。 有時這會成為一種意外的祝福,因為我們可能會更努力地保持依賴項的最小化。
5. 結論
本文簡要介紹了兩種使用 基於構造器的依賴注入方式,並使用了 Spring 框架。