4. Spring對IoC的實現

捞月亮的小北發表於2024-06-25

1. IoC 控制反轉

對控制反轉的理解:

控制反轉是一種思想。

控制反轉是為了降低程式耦合度,提高程式擴充套件力,達到OCP原則,達到DIP原則。

控制反轉,反轉的是什麼?

  • 將物件的建立權利交出去,交給第三方容器負責。(我的理解:也就是不用自己new 物件了 , 交給Spring容器進行處理)
  • 將物件和物件之間關係的維護權交出去,交給第三方容器負責。

控制反轉這種思想如何實現呢?

  • DI(Dependency Injection):依賴注入 (控制反轉的具體實現)

2. 依賴注入

對依賴注入的理解

依賴注入實現了控制反轉的思想。

Spring透過依賴注入的方式來完成Bean管理的。

Bean管理說的是:Bean物件的建立,以及Bean物件中屬性的賦值(或者叫做Bean物件之間關係的維護)。

依賴注入:

  • 依賴指的是物件和物件之間的關聯關係。
  • 注入指的是一種資料傳遞行為,透過注入行為來讓物件和物件產生關係。

依賴注入常見的實現方式包括兩種:

  • 第一種:set注入
  • 第二種:構造注入

2.1 set 注入

set注入,基於set方法實現的,底層會透過反射機制呼叫屬性對應的set方法然後給屬性賦值。這種方式要求屬性必須對外提供set方法。

重點內容:

<?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="userDaoBean" class="com.north.spring6.dao.UserDao"/>

    <bean id="userServiceBean" class="com.north.spring6.service.UserService">
        <property name="userDao" ref="userDaoBean"/>
    </bean>

</beans>

實現原理

透過property標籤獲取到屬性名:userDao

透過屬性名推斷出set方法名:setUserDao

透過反射機制呼叫setUserDao()方法給屬性賦值

property標籤的name是屬性名。

property標籤的ref是要注入的bean物件的id。(透過ref屬性來完成bean的裝配,這是bean最簡單的一種裝配方式。裝配指的是:建立系統元件之間關聯的動作)

透過測試看到程式仍然可以正常執行,說明property標籤的name是:setUserDao()方法名演變得到的。演變的規律是:

  • setUsername() 演變為 username
  • setPassword() 演變為 password
  • setUserDao() 演變為 userDao
  • setUserService() 演變為 userService

另外,對於property標籤來說,ref屬性也可以採用標籤的方式,但使用ref屬性是多數的:

<bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
  <property name="userDao">
    <ref bean="userDaoBean"/>
  </property>
</bean>

總結:set注入的核心實現原理:透過反射機制呼叫set方法來給屬性賦值,讓兩個物件之間產生關係。

2.2 構造注入

核心原理:透過呼叫構造方法來給屬性賦值。

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="userDaoBean" class="com.north.spring6.dao.UserDao"></bean>

    <bean id="userServiceBean" class="com.north.spring6.service.UserService">
        <!--第一種配置方式-->
        <!--<constructor-arg ref="userDaoBean"></constructor-arg>-->
        <!--第二種配置方式-->
        <!--<constructor-arg index="0" ref="userDaoBean"></constructor-arg>-->
        <!--第三種配置方式-->
        <constructor-arg name="userDao" ref="userDaoBean"></constructor-arg>
    </bean>
</beans>

透過測試得知,透過構造方法注入的時候:

  • 可以透過下標
  • 可以透過引數名
  • 也可以不指定下標和引數名,可以型別自動推斷

Spring在裝配方面做的還是比較健壯的。

3. set 注入專題

3.1 注入外部 bean

外部Bean的特點:bean定義到外面,在property標籤中使用ref屬性進行注入。通常這種方式是常用。

<?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="userDaoBean" class="com.north.spring6.dao.UserDao"/>

    <bean id="userServiceBean" class="com.north.spring6.service.UserService">
        <property name="userDao" ref="userDaoBean"/>
    </bean>

</beans>

3.2 注入內部 bean

內部Bean的方式:在bean標籤中巢狀bean標籤。

<?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="userServiceBean" class="com.north.spring6.service.UserService">
        <property name="userDao">
            <bean class="com.north.spring6.dao.UserDao"/>
        </property>
    </bean>

</beans>

3.3 注入簡單型別

需要特別注意:如果給簡單型別賦值,使用value屬性或value標籤。而不是ref。

透過原始碼分析得知,簡單型別包括:

  • 基本資料型別
  • 基本資料型別對應的包裝類
  • String或其他的CharSequence子類
  • Number子類
  • Date子類
  • Enum子類
  • URI
  • URL
  • Temporal子類
  • Locale
  • Class
  • 另外還包括以上簡單值型別對應的陣列型別。

3.4 級聯屬性賦值 (瞭解)

<?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="clazzBean" class="com.north.spring6.beans.Clazz"/>

    <bean id="student" class="com.north.spring6.beans.Student">
        <property name="name" value="張三"/>

        <!--要點1:以下兩行配置的順序不能顛倒-->
        <property name="clazz" ref="clazzBean"/>
        <!--要點2:clazz屬性必須有getter方法-->
        <property name="clazz.name" value="高三一班"/>
    </bean>
</beans>

要點:

  • 在spring配置檔案中,如上,注意順序。
  • 在spring配置檔案中,clazz屬性必須提供getter方法。

3.5 注入陣列

3.6 注入List集合

3.7 注入Set集合

3.8 注入Map集合

3.9 注入Properties

3.10 注入null和空字串

3.11 注入的值中含有特殊符號

4. 基於p名稱空間的注入

P名稱空間注入:底層實際上還是set​注入 , 用於簡化set​注入 , 注意:不能省略set方法

5. 基於c名稱空間的注入

基於構造放啊​ , 簡化構造注入​ , 注意:不能省略構造方法

6. util 名稱空間讓配置複用

7. 基於XML的自動裝配

7.1 根據名稱自動裝配

7.2 根據型別自動裝配

8. Spring 引入外部屬性配置檔案

相關文章