前言
通過IOC控制反轉的學習,我們已經知道了如果将類的建立進行控制反轉,并使用Spring容器來管理;也知道了如何建立Spring容器,從中擷取Bean。
但是當我們一個類中定義了其他基本類型或引用類型的屬性,那麼怎麼在從Spring容器中擷取Bean的同時,也能夠讓Bean中的屬性賦上值呢?
這就是我們要學習的DI依賴注入。
依賴注入簡介
當某個角色(可能是一個Java執行個體,調用者)需要另一個角色(另一個Java執行個體,被調用者)的協助時,在 傳統的程式設計過程中,通常由調用者來建立被調用者的執行個體。
但在Spring裡,建立被調用者的工作不再由調用者來完成,是以稱為控制反轉;建立被調用者執行個體的工作通常由Spring容器來完成,然後注入調用者,是以也稱為依賴注入。
簡而言之,依賴注入就是在Spring容器中擷取一個Bean的同時,讓這個Bean中需要的屬性、參數也能擷取到對應的值。
依賴注入的方式
- 通過構造方法進行注入
- 通過set方法進行注入
DI入門案例
- 通過構造方式進行注入
- User實體類
/** * 使用者實體類 */ public class User { private String name; //姓名 private int age; //年齡 public User(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
- applicationContext配置檔案
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 配置User id:表示此bean的唯一辨別 class:指定要建立對象的類的位元組碼對象 --> <bean id="user" class="com.itheima.entity.User"> <!-- 當通過構造方法注入時,使用constructor-arg标簽 name:對應構造方法的參數 value:對name指定的參數進行指派,無論字元和數字都用雙引号 --> <constructor-arg name="name" value="張三"/> <constructor-arg name="age" value="25"/> </bean> </beans>
- 測試代碼
public class Test { public static void main(String[] args) { //加載配置檔案,建立Spring容器 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //擷取Bean User user = context.getBean("user", User.class); System.out.println(user); } }
- 結果
- User實體類
- 通過set方法注入
- User1實體類
/** * 使用者實體類 */ public class User1 { private String name; //姓名 private int age; //年齡 public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
- applicationContext.xml配置檔案
<!-- 配置User1 id:表示此bean的唯一辨別 class:指定要建立對象的類的位元組碼對象 --> <bean id="user1" class="com.itheima.entity.User1"> <!-- 當通過set方法注入時,使用property标簽 name:對應set方法的方法名(例如setName方法,去掉setN -> 對應的是:name) value:對name指定的參數進行指派,無論字元和數字都用雙引号 --> <property name="name" value="李四"/> <property name="age" value="56"/> </bean>
- 測試類
public class Test1 { public static void main(String[] args) { //加載配置檔案,建立Spring容器 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //擷取Bean User1 user1 = context.getBean("user1", User1.class); System.out.println(user1); } }
- 結果
- User1實體類
多種類型依賴注入
屬性類型分類
- 基本類型包裝類,比如 Integer、Double、Boolean;
- 字元串類型,比如 String;
- 集合類型,比如 list、set、map 。
- 類類型,比如 其餘定義的 java 類;
代碼資料準備
//使用者實體類
public class User {
private Integer id;
private String name;
private Object [] array;
private List list;
private Map map;
//省略get和set方法
}
以下根據這個實體類來示範各個屬性類型的依賴注入。
基本類型和字元串類型
對于基本類型和字元串類型,在 xml 的配置檔案中,通過 value 屬性即可以指派,在入門案例中已經使用。
數組類型
- 配置檔案編寫
<!-- 數組的屬性注入 id:設定bean的唯一辨別,擷取Bean的時候根據id進行擷取 class:要建立對象的類的位元組碼對象,對象建立後會由Spring進行管理 --> <bean id="user" class="com.offcn.entity.User"> <property name="array"> <array> <value>tom</value> <value>jerry</value> </array> </property> </bean>
- 配置解釋
- property 中的 name Java類中數組的set方法的名字 如:SetArray 去掉Set ,A小寫,得到array;name隻與set方法有關。 property表示通過set方法注入。
- array 标簽是固定的,不能變化,表示屬性是一個數組,是以加在了 property 的屬性内部。
- value 表示數組中的值,因為數組可以存儲多個值,是以每一個數組的值,通過一個 value 标簽聲明。
集合類型
- list集合依賴注入
- 配置檔案編寫
<!-- 集合的屬性注入 --> <bean id="user" class="com.offcn.entity.User"> <property name="list"> <list> <value>笑傲江湖</value> <value>俠客行</value> <value>連城訣</value> </list> </property> </bean>
- 配置解釋
- property 中的 name 是 java 類中List集合的set方法名,表示通過set方法注入,name隻與set方法名有關。
- list 标簽是固定的,不能變化,表示屬性是一個 list 集合 ,是以加在了 property 的屬性内部
- value 表示集合中的值,因為集合可以存儲多個值,是以每一個集合中的值,通過一個 value 标簽聲明.
- List集合與Set集合相同
- 配置檔案編寫
- map集合依賴注入
- 配置檔案編寫
<bean id="user" class="com.offcn.entity.User"> <property name="map"> <map> <entry key="小亮" value="小路"></entry> <entry key="文同學" value="伊利姐"></entry> </map> </property> </bean>
- 配置解釋
- property 中的 name 是 java 類中List集合的set方法名,表示通過set方法注入,name隻與set方法名有關。
- map 标簽是固定的,不能變化,表示屬性是一個 map 集合 ,是以加在了 property 的屬性内部。
- entry 标簽固定表示 map 中的一對鍵值對,map 也可以存儲多對,是以 key 表示鍵值對的鍵,value 表示鍵值對的值。
- 配置檔案編寫
類類型
一個類中依賴另一個類的情況;就像我們編寫三層架構的時候,表現層依賴業務邏輯層,業務邏輯層依賴資料通路層;隻有資料通路層與資料庫打交道。
以下我們就模拟一下 業務邏輯層依賴資料通路層的情況;也就是說在邏輯層中,有資料通路層類的成員變量屬性。
資料準備
- 資料通路層 UserDao
/** * 模拟關于使用者的資料通路層 */ public class UserDao { /** * 模拟儲存使用者 */ public void saveUser() { System.out.println("我是UserDao中的儲存使用者的方法!"); } }
- 業務邏輯層 UserService
/** * 模拟使用者業務邏輯層 */ public class UserService { //依賴資料通路層 private UserDao userDao; //提供set方法,友善依賴注入 public void setUserDao(UserDao userDao) { this.userDao = userDao; } /** * 儲存使用者方法 */ public void saveUser() { //調用資料通路層的儲存使用者方法 userDao.saveUser(); } }
- 編寫Spring配置檔案
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"> <!--先要配置資料通路層UserDao--> <bean id="userDao" class="com.my.Dao.UserDao"/> <!--配置業務邏輯層--> <bean id="userService" class="com.my.service.UserService"> <!-- 通過Set方法注入UserDao name:對應UserService類中的Set方法的名字 ref:(reference:引用),表示這個屬性引用上面配置的UserDao的id,這樣就能實作類類型的注入 --> <property name="userDao" ref="userDao"/> </bean> </beans>
- 配置說明
- property:表示通過Set方法進行依賴注入。
- name:對應UserService類中的Set方法的名字,name隻與Set方法名相關。
- ref:表示這個屬性引用上面配置的UserDao的id,這樣就能實作類類型的注入,當我們從Spring中擷取UserServices示例對象的時候,Spring會将UserServices對象依賴的UserDao執行個體對象,一并完成依賴注入。
- 測試代碼
/** * 測試類 */ public class UserServiceTest { /** * 儲存使用者方法測試 */ @Test public void userSaveTest() { //建立spring容器,參數指定spring配置檔案的全名 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //擷取Bean UserService userService = context.getBean("userService", UserService.class); //調用儲存使用者方法 userService.saveUser(); } }
- 結果
總結
以上就是Spring的xml配置依賴注入的方式,在xml配置的時候一步一步來,看清楚一個類中依賴了哪些類,然後進行各個類的配置。