依賴注入(Dependency Injection,DI)和控制反轉含義相同,它們是從兩個角度描述的同一個概念。
當某個 Java 實例需要另一個 Java 實例時,傳統的方法是由調用者創建被調用者的實例(例如,使用 new 關鍵字獲得被調用者實例),而使用 Spring 框架后,被調用者的實例不再由調用者創建,而是由 Spring 容器創建,這稱為控制反轉。
Spring 容器在創建被調用者的實例時,會自動將調用者需要的對象實例注入給調用者,這樣,調用者通過 Spring 容器獲得被調用者實例,這稱為依賴注入。
依賴注入主要有兩種實現方式,分別是屬性 setter 注入和構造方法注入。具體介紹如下。
1)屬性 setter 注入
指 IoC 容器使用 setter 方法注入被依賴的實例。通過調用無參構造器或無參 static 工廠方法實例化 bean 后,調用該 bean 的 setter 方法,即可實現基於 setter 的 DI。
2)構造方法注入
指 IoC 容器使用構造方法注入被依賴的實例。基於構造器的 DI 通過調用帶參數的構造方法實現,每個參數代表一個依賴。
下面通過屬性 setter 注入的案例演示 Spring 容器是如何實現依賴注入的。具體步驟如下。
1. 創建 IUserService 接口
在 SpringDemo1 項目的 com.liuhao.service 包下創建一個名為 IUserService 的接口,該接口中包含一個 add() 方法,如下所示。
1 package com.liuhao.service; 2 public interface IUserService { 3 public void add(); 4 }
2. 創建接口實現類 UserServiceImpl
在 com.liuhao.service 包下創建一個名為 UserServiceImpl 的類,該類實現了 IUserService 接口,如下所示。
1 package com.liuhao.service; 2 public class UserServiceImpl implements IUserService { 3 // 定義接口聲明 4 private IUserDao userDao; 5 // 提供set()方法,用於依賴注入 6 public void setUserDao(IUserDao userDao) { 7 this.userDao = userDao; 8 } 9 // 實現IUserService接口的方法 10 @Override 11 public void add() { 12 userDao.add(); // 調用IUserDao中的add()方法 13 System.out.println("調用Service層add方法成功!!!"); 14 } 15 }
上述代碼中,首先聲明了 userDao 對象,並為其添加 setter 方法,用於依賴注入,然后實現了 IUserDao 接口的 add() 方法,並在方法中調用 add() 方法和輸出一條語句。
3. 在 applicationContext.xml 中添加配置信息
在 applicationContext.xml 配置文件中添加一個 <bean> 元素,用於實例化 UserServiceImpl 類,並將 userDao 的實例注入到 userService 中,其實現代碼如下所示:
1 <bean id="userService" class="com.liuhao.service.UserServiceImpl"> 2 <!-- 將userDao實例注入userService實例中 --> 3 <property name="userDao" ref="userDao"/> 4 </bean>
4. 編寫測試方法
在 Test 類編輯后如下所示:
1 package com.liuhao.dao; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 public class Test { 7 8 public static void main(String[] args) { 9 // 創建 ioc 容器 ,加載配置文件 10 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 11 // 通過容器獲取userService實例 12 IUserService userService = (IUserService) context.getBean("userService"); 13 // 調用userService的add()方法 14 userService.add(); 15 } 16 17 }
5. 運行項目並查看結果
運行成功后,控制台的輸出結果如圖所示。
從圖的輸出結果中可以看出,使用 Spring 容器獲取 userService 的實例后,調用了該實例的 add() 方法,在該方法中又調用了 IUserDao 實現類中的 add() 方法,並輸出了結果。這就是 Spring 容器屬性 setter 注入的方式,也是實際開發中較為常用的一種方式。