<input id="ohw05"></input>
  • <table id="ohw05"><menu id="ohw05"></menu></table>
  • <var id="ohw05"></var>
  • <code id="ohw05"><cite id="ohw05"></cite></code>
    <label id="ohw05"></label>
    <var id="ohw05"></var>
  • Java開發學習(六)----DI依賴注入之setter及構造器注入解析

    一、DI依賴注入

    首先來介紹下Spring中有哪些注入方式?

    我們先來思考

    • 向一個類中傳遞數據的方式有幾種?

      • 普通方法(set方法)

      • 構造方法

    • 依賴注入描述了在容器中建立bean與bean之間的依賴關系的過程,如果bean運行需要的是數字或字符串呢?

      • 引用類型

      • 簡單類型(基本數據類型與String)

    Spring就是基于上面這些知識點,為我們提供了兩種注入方式,分別是:

    • setter注入

      • 簡單類型

      • 引用類型

    • 構造器注入

      • 簡單類型

      • 引用類型

    依賴注入的方式已經介紹完,接下來挨個看下:

    二、setter注入

    1. 對于setter方式注入引用類型的方式之前已經介紹過,簡單看下:

    • 在bean中定義引用類型屬性,并提供可訪問的set方法

    public class BookServiceImpl implements BookService {
        private BookDao bookDao;
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    }
    • 配置中使用property標簽ref屬性注入引用類型對象

    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
    </bean>
    ?
    <bean id="bookDao" class="com.itheima.dao.imipl.BookDaoImpl"/>

    2.1 環境準備

    環境準備:

    • 創建一個Maven項目

    • pom.xml添加依賴

    • resources下添加spring的配置文件

    最終項目的結構如下:

    (1)項目中添加BookDao、BookDaoImpl、UserDao、UserDaoImpl、BookService和BookServiceImpl類

    public interface BookDao {
        public void save();
    }
    ?
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ...");
        }
    }
    public interface UserDao {
        public void save();
    }
    public class UserDaoImpl implements UserDao {
        public void save() {
            System.out.println("user 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)編寫AppForDISet運行類,加載Spring的IOC容器,并從中獲取對應的bean對象

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

    2.2 注入引用數據類型

    需求:在bookServiceImpl對象中注入userDao

    1.在BookServiceImpl中聲明userDao屬性

    2.為userDao屬性提供setter方法

    3.在配置文件中使用property標簽注入

    步驟1:聲明屬性并提供setter方法

    在BookServiceImpl中聲明userDao屬性,并提供setter方法

    public class BookServiceImpl implements BookService{
        private BookDao bookDao;
        private UserDao userDao;
        
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    ?
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
            userDao.save();
        }
    }
    步驟2:配置文件中進行注入配置

    在applicationContext.xml配置文件中使用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 id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
        <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
            <property name="bookDao" ref="bookDao"/>
            <property name="userDao" ref="userDao"/>
        </bean>
    </beans>
    步驟3:運行程序

    運行AppForDISet類,查看結果,說明userDao已經成功注入。

    2.3 注入簡單數據類型

    需求:給BookDaoImpl注入一些簡單數據類型的數據

    參考引用數據類型的注入,我們可以推出具體的步驟為:

    1.在BookDaoImpl類中聲明對應的簡單數據類型的屬性

    2.為這些屬性提供對應的setter方法

    3.在applicationContext.xml中配置

    思考:

    引用類型使用的是<property name="" ref=""/>,簡單數據類型還是使用ref么?

    ref是指向Spring的IOC容器中的另一個bean對象的,對于簡單數據類型,沒有對應的bean對象,該如何配置?

    步驟1:聲明屬性并提供setter方法

    在BookDaoImpl類中聲明對應的簡單數據類型的屬性,并提供對應的setter方法

    public class BookDaoImpl implements BookDao {
    ?
        private String databaseName;
        private int connectionNum;
    ?
        public void setConnectionNum(int connectionNum) {
            this.connectionNum = connectionNum;
        }
    ?
        public void setDatabaseName(String databaseName) {
            this.databaseName = databaseName;
        }
    ?
        public void save() {
            System.out.println("book dao save ..."+databaseName+","+connectionNum);
        }
    }
    步驟2:配置文件中進行注入配置

    在applicationContext.xml配置文件中使用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">
            <property name="databaseName" value="mysql"/>
            <property name="connectionNum" value="10"/>
        </bean>
        <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
        <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
            <property name="bookDao" ref="bookDao"/>
            <property name="userDao" ref="userDao"/>
        </bean>
    </beans>

    說明:

    value:后面跟的是簡單數據類型,對于參數類型,Spring在注入的時候會自動轉換,但是不能寫成

    <property name="connectionNum" value="abc"/>

    這樣的話,spring在將abc轉換成int類型的時候就會報錯。

    步驟3:運行程序

    運行AppForDISet類,查看結果,說明userDao已經成功注入。

    注意:兩個property注入標簽的順序可以任意。

    對于setter注入方式的基本使用就已經介紹完了,

    • 對于引用數據類型使用的是<property name="" ref=""/>

    • 對于簡單數據類型使用的是<property name="" value=""/>

    三、構造器注入

    3.1 環境準備

    構造器注入也就是構造方法注入,還是先準備下環境:

    • 創建一個Maven項目

    • pom.xml添加依賴

    • resources下添加spring的配置文件

    這些步驟和前面的都一致,大家可以快速的拷貝即可,最終項目的結構如下:

    (1)項目中添加BookDao、BookDaoImpl、UserDao、UserDaoImpl、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 UserDao {
        public void save();
    }
    public class UserDaoImpl implements UserDao {
        public void save() {
            System.out.println("user 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)編寫AppForDIConstructor運行類,加載Spring的IOC容器,并從中獲取對應的bean對象

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

    3.2 構造器注入引用數據類型

    接下來,在上面這個環境中來完成構造器注入:

    需求:將BookServiceImpl類中的bookDao修改成使用構造器的方式注入。

    1.將bookDao的setter方法刪除掉

    2.添加帶有bookDao參數的構造方法

    3.在applicationContext.xml中配置

    步驟1:刪除setter方法并提供構造方法

    在BookServiceImpl類中將bookDao的setter方法刪除掉,并添加帶有bookDao參數的構造方法

    public class BookServiceImpl implements BookService{
        private BookDao bookDao;
    ?
        public BookServiceImpl(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    ?
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
    步驟2:配置文件中進行配置構造方式注入

    在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"/>
        <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
            <constructor-arg name="bookDao" ref="bookDao"/>
        </bean>
    </beans>

    說明:

    標簽<constructor-arg>

    • name屬性對應的值為構造函數中方法形參的參數名,必須要保持一致。

    • ref屬性指向的是spring的IOC容器中其他bean對象。

    步驟3:運行程序

    運行AppForDIConstructor類,查看結果,說明bookDao已經成功注入。

    3.3 構造器注入多個引用數據類型

    需求:在BookServiceImpl使用構造函數注入多個引用數據類型,比如userDao

    1.聲明userDao屬性

    2.生成一個帶有bookDao和userDao參數的構造函數

    3.在applicationContext.xml中配置注入

    步驟1:提供多個屬性的構造函數

    在BookServiceImpl聲明userDao并提供多個參數的構造函數

    public class BookServiceImpl implements BookService{
        private BookDao bookDao;
        private UserDao userDao;
    ?
        public BookServiceImpl(BookDao bookDao,UserDao userDao) {
            this.bookDao = bookDao;
            this.userDao = userDao;
        }
    ?
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
            userDao.save();
        }
    }
    步驟2:配置文件中配置多參數注入

    在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"/>
        <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
        <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
            <constructor-arg name="bookDao" ref="bookDao"/>
            <constructor-arg name="userDao" ref="userDao"/>
        </bean>
    </beans>

    說明:這兩個<contructor-arg>的配置順序可以任意

    步驟3:運行程序

    運行AppForDIConstructor類,查看結果,說明userDao已經成功注入。

    3.4 構造器注入多個簡單數據類型

    需求:在BookDaoImpl中,使用構造函數注入databaseName和connectionNum兩個參數。

    參考引用數據類型的注入,我們可以推出具體的步驟為:

    1.提供一個包含這兩個參數的構造方法

    2.在applicationContext.xml中進行注入配置

    步驟1:添加多個簡單屬性并提供構造方法

    修改BookDaoImpl類,添加構造方法

    public class BookDaoImpl implements BookDao {
        private String databaseName;
        private int connectionNum;
    ?
        public BookDaoImpl(String databaseName, int connectionNum) {
            this.databaseName = databaseName;
            this.connectionNum = connectionNum;
        }
    ?
        public void save() {
            System.out.println("book dao save ..."+databaseName+","+connectionNum);
        }
    }
    步驟2:配置完成多個屬性構造器注入

    在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">
            <constructor-arg name="databaseName" value="mysql"/>
            <constructor-arg name="connectionNum" value="666"/>
        </bean>
        <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
        <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
            <constructor-arg name="bookDao" ref="bookDao"/>
            <constructor-arg name="userDao" ref="userDao"/>
        </bean>
    </beans>

    說明:這兩個<contructor-arg>的配置順序可以任意

    步驟3:運行程序

    運行AppForDIConstructor類,查看結果

    上面已經完成了構造函數注入的基本使用,但是會存在一些問題:

    • 當構造函數中方法的參數名發生變化后,配置文件中的name屬性也需要跟著變,因為是形參的名字。

    • 這兩塊存在緊耦合,具體該如何解決?

    在解決這個問題之前,需要提前說明的是,這個參數名發生變化的情況并不多,所以上面的還是比較主流的配置方式,下面介紹的,大家都以了解為主。

    方式一:刪除name屬性,添加type屬性,按照類型注入

    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <constructor-arg type="int" value="10"/>
        <constructor-arg type="java.lang.String" value="mysql"/>
    </bean>
    • 這種方式可以解決構造函數形參名發生變化帶來的耦合問題

    • 但是如果構造方法參數中有類型相同的參數,這種方式就不太好實現了

    方式二:刪除type屬性,添加index屬性,按照索引下標注入,下標從0開始

    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <constructor-arg index="1" value="100"/>
        <constructor-arg index="0" value="mysql"/>
    </bean>
    • 這種方式可以解決參數類型重復問題

    • 但是如果構造方法參數順序發生變化后,這種方式又帶來了耦合問題

    介紹完兩種參數的注入方式,具體我們該如何選擇呢?

    1. 強制依賴使用構造器進行,使用setter注入有概率不進行注入導致null對象出現

      • 強制依賴指對象在創建的過程中必須要注入指定的參數

    2. 可選依賴使用setter注入進行,靈活性強

      • 可選依賴指對象在創建過程中注入的參數可有可無

    3. Spring框架倡導使用構造器,第三方框架內部大多數采用構造器注入的形式進行數據初始化,相對嚴謹

    4. 如果有必要可以兩者同時使用,使用構造器注入完成強制依賴的注入,使用setter注入完成可選依賴的注入

    5. 實際開發過程中還要根據實際情況分析,如果受控對象沒有提供setter方法就必須使用構造器注入

    6. 自己開發的模塊推薦使用setter注入

    四、總結

    這里主要講的是Spring的依賴注入的實現方式:

    • setter注入

      • 簡單數據類型

        <bean ...>
            <property name="" value=""/>
        </bean>
      • 引用數據類型

        <bean ...>
            <property name="" ref=""/>
        </bean>
    • 構造器注入

      • 簡單數據類型

        <bean ...>
            <constructor-arg name="" index="" type="" value=""/>
        </bean>
      • 引用數據類型

        <bean ...>
            <constructor-arg name="" index="" type="" ref=""/>
        </bean>
    • 依賴注入的方式選擇上

      • 建議使用setter注入

      • 第三方技術根據情況選擇

     

    posted @ 2022-06-27 22:26  |舊市拾荒|  閱讀(130)  評論(0編輯  收藏  舉報
    国产美女a做受大片观看