Java開發學習(七)----DI依賴注入之自動裝配與集合注入

2022-07-05 06:01:32

一、自動設定

上一篇部落格花了大量的時間把Spring的注入去學習了下,總結起來就兩個字麻煩。麻煩在組態檔的編寫設定上。那有更簡單方式麼?有,自動設定

1.1 依賴自動裝配

  • IoC容器根據bean所依賴的資源在容器中自動查詢並注入到bean中的過程稱為自動裝配

1.2 自動裝配方式

  • 按型別(常用)

  • 按名稱

  • 按構造方法

  • 不啟用自動裝配

1.3 環境準備

  • 建立一個Maven專案

  • pom.xml新增依賴

  • resources下新增spring的組態檔

最終專案的結構如下:

(1)專案中新增BookDao、BookDaoImpl、BookService和BookServiceImpl類

public interface BookDao {
    public void save();
}
​
public class BookDaoImpl implements BookDao {
    
    private String databaseName;
    private int connectionNum;
    
    public void save() {
        System.out.println("book dao save ...");
    }
}
public interface BookService {
    public void save();
}
​
public class BookServiceImpl implements BookService{
    private BookDao bookDao;
​
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
​
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

(2)resources下提供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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
​
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
    </bean>
</beans>

(3)編寫AppForAutoware執行類,載入Spring的IOC容器,並從中獲取對應的bean物件

public class AppForAutoware {
    public static void main( String[] args ) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookService bookService = (BookService) ctx.getBean("bookService");
        bookService.save();
    }
}

1.4 完成自動裝配的設定

接下來,在上面這個環境中來完成自動裝配:

自動裝配只需要修改applicationContext.xml組態檔即可:

(1)將<property>標籤刪除

(2)在<bean>標籤中新增autowire屬性

首先來實現按照型別注入的設定

<?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">
​
    <bean class="com.itheima.dao.impl.BookDaoImpl"/>
    <!--autowire屬性:開啟自動裝配,通常使用按型別裝配-->
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
​
</beans>

注意事項:

  • 需要注入屬性的類中對應屬性的setter方法不能省略

  • 被注入的物件必須要被Spring的IOC容器管理

  • 按照型別在Spring的IOC容器中如果找到多個物件,會報NoUniqueBeanDefinitionException

一個型別在IOC中有多個物件,還想要注入成功,這個時候就需要按照名稱注入,設定方式為:

<?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">
​
    <bean class="com.itheima.dao.impl.BookDaoImpl"/>
    <!--autowire屬性:開啟自動裝配,通常使用按型別裝配-->
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byName"/>
​
</beans>

注意事項:

  • 按照名稱注入中的名稱指的是什麼?

    • bookDao是private修飾的,外部類無法直接方法

    • 外部類只能通過屬性的set方法進行存取

    • 對外部類來說,setBookDao方法名,去掉set後首字母小寫是其屬性名

      • 為什麼是去掉set首字母小寫?

      • 這個規則是set方法生成的預設規則,set方法的生成是把屬性名首字母大寫前面加set形成的方法名

    • 所以按照名稱注入,其實是和對應的set方法有關,但是如果按照標準起名稱,屬性名和set對應的名是一致的

  • 如果按照名稱去找對應的bean物件,找不到則注入Null

  • 當某一個型別在IOC容器中有多個物件,按照名稱注入只找其指定名稱對應的bean物件,不會報錯

兩種方式介紹完後,以後用的更多的是按照型別注入。

最後對於依賴注入,需要注意一些其他的設定特徵:

  1. 自動裝配用於參照型別依賴注入,不能對簡單型別進行操作

  2. 使用按型別裝配時(byType)必須保障容器中相同型別的bean唯一,推薦使用

  3. 使用按名稱裝配時(byName)必須保障容器中具有指定名稱的bean,因變數名與設定耦合,不推薦使用

  4. 自動裝配優先順序低於setter注入與構造器注入,同時出現時自動裝配設定失效

二、集合注入

上一篇部落格我們已經能完成引入資料型別和簡單資料型別的注入,但是還有一種資料型別集合,集合中既可以裝簡單資料型別也可以裝參照資料型別,對於集合,在Spring中該如何注入呢?

常見的集合型別有如下幾種

  • 陣列

  • List

  • Set

  • Map

  • Properties

針對不同的集合型別,該如何實現注入呢?

2.1 環境準備

  • 建立一個Maven專案

  • pom.xml新增依賴

  • resources下新增spring的組態檔applicationContext.xml

最終專案的結構如下:

(1)專案中新增新增BookDao、BookDaoImpl類

public interface BookDao {
    public void save();
}
​
public class BookDaoImpl implements BookDao {
    
public class BookDaoImpl implements BookDao {
​
    private int[] array;
​
    private List<String> list;
​
    private Set<String> set;
​
    private Map<String,String> map;
​
    private Properties properties;
​
     public void save() {
        System.out.println("book dao save ...");
​
        System.out.println("遍歷陣列:" + Arrays.toString(array));
​
        System.out.println("遍歷List" + list);
​
        System.out.println("遍歷Set" + set);
​
        System.out.println("遍歷Map" + map);
​
        System.out.println("遍歷Properties" + properties);
    }
    //setter....方法省略,自己使用工具生成
}

(2)resources下提供spring的組態檔,applicationContext.xml

<?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">
​
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>

(3)編寫AppForDICollection執行類,載入Spring的IOC容器,並從中獲取對應的bean物件

public class AppForDICollection {
    public static void main( String[] args ) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
    }
}

接下來,在上面這個環境中來完成集合注入:

下面的所以設定方式,都是在bookDao的bean標籤中使用<property>進行注入

<?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">
​
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        
    </bean>
</beans>

2.2 注入陣列型別

<property name="array">
    <array>
        <value>100</value>
        <value>200</value>
        <value>300</value>
    </array>
</property>

2.3 注入List型別

<property name="list">
    <list>
        <value>itcast</value>
        <value>itheima</value>
        <value>boxuegu</value>
        <value>chuanzhihui</value>
    </list>
</property>

2.4 注入Set型別

<property name="set">
    <set>
        <value>itcast</value>
        <value>itheima</value>
        <value>boxuegu</value>
        <value>boxuegu</value>
    </set>
</property>

2.5 注入Map型別

<property name="map">
    <map>
        <entry key="country" value="china"/>
        <entry key="province" value="henan"/>
        <entry key="city" value="kaifeng"/>
    </map>
</property>

2.6 注入Properties型別

<property name="properties">
    <props>
        <prop key="country">china</prop>
        <prop key="province">henan</prop>
        <prop key="city">kaifeng</prop>
    </props>
</property>

設定完成後,執行下看結果:

說明:

  • property標籤表示setter方式注入,構造方式注入constructor-arg標籤內部也可以寫<array><list><set><map><props>標籤

  • List的底層也是通過陣列實現的,所以<list><array>標籤是可以混用

  • 集合中要新增參照型別,只需要把<value>標籤改成<ref>標籤,這種方式用的比較少