1. 程式人生 > >依賴注入的三種方式

依賴注入的三種方式

Spring通過DI(依賴注入)實現IOC(控制反轉),常用的注入方式主要有三種:構造方法注入,setter注入,基於註解的注入。

構造方法注入

先簡單看一下測試專案的結構,用maven構建的,四個包:
entity:儲存實體,裡面只有一個User類
dao:資料訪問,一個介面,兩個實現類
service:服務層,一個介面,一個實現類,實現類依賴於IUserDao
test:測試包 
這裡寫圖片描述 
在spring的配置檔案中註冊UserService,將UserDaoJdbc通過constructor-arg標籤注入到UserService的某個有引數的構造方法

<!-- 註冊userService -->
<bean
id="userService" class="com.lyu.spring.service.impl.UserService">
<constructor-arg ref="userDaoJdbc"></constructor-arg> </bean> <!-- 註冊jdbc實現的dao --> <bean id="userDaoJdbc" class="com.lyu.spring.dao.impl.UserDaoJdbc"></bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

如果只有一個有引數的構造方法並且引數型別與注入的bean的型別匹配,那就會注入到該構造方法中。

public class UserService implements IUserService {

    private IUserDao userDao;

    public UserService(IUserDao userDao) {
        this.userDao = userDao;
    }

    public void loginUser() {
        userDao.loginUser();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
@Test
public void testDI() {
    ApplicationContext ac = new
ClassPathXmlApplicationContext("applicationContext.xml"); // 獲取bean物件 UserService userService = ac.getBean(UserService.class, "userService"); // 模擬使用者登入 userService.loginUser(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

測試列印結果:jdbc-登入成功

注:模擬使用者登入的loginUser方法其實只是列印了一條輸出語句,jdbc實現的類輸出的是:jdbc-登入成功,mybatis實現的類輸出的是:mybatis-登入成功。 

問題一:如果有多個有引數的構造方法並且每個構造方法的引數列表裡面都有要注入的屬性,那userDaoJdbc會注入到哪裡呢?

public class UserService implements IUserService {

    private IUserDao userDao;
    private User user;

    public UserService(IUserDao userDao) {
        System.out.println("這是有一個引數的構造方法");
        this.userDao = userDao;
    }

    public UserService(IUserDao userDao, User user) {
        System.out.println("這是有兩個引數的構造方法");
        this.userDao = userDao;
        this.user = user;
    }

    public void loginUser() {
        userDao.loginUser();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21


結果:會注入到只有一個引數的構造方法中,並且經過測試注入哪一個構造方法與構造方法的順序無關

這裡寫圖片描述

問題二:如果只有一個構造方法,但是有兩個引數,一個是待注入的引數,另一個是其他型別的引數,那麼這次注入可以成功嗎?

public class UserService implements IUserService {

    private IUserDao userDao;
    private User user;

    public UserService(IUserDao userDao, User user) {
        this.userDao = userDao;
        this.user = user;
    }

    public void loginUser() {
        userDao.loginUser();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

結果:失敗了,即使在costract-arg標籤裡面通過name屬性指定要注入的引數名userDao也會失敗.

這裡寫圖片描述

問題三:如果我們想向有多個引數的構造方法中注入值該在配置檔案中怎麼寫呢?

public class UserService implements IUserService {

    private IUserDao userDao;
    private User user;

    public UserService(IUserDao userDao, User user) {
        this.userDao = userDao;
        this.user = user;
    }

    public void loginUser() {
        userDao.loginUser();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

參考寫法:通過name屬性指定要注入的值,與構造方法引數列表引數的順序無關。

<!-- 註冊userService -->
<bean id="userService" class="com.lyu.spring.service.impl.UserService">
    <constructor-arg name="userDao" ref="userDaoJdbc"></constructor-arg>
    <constructor-arg name="user" ref="user"></constructor-arg>
</bean>

<!-- 註冊實體User類,用於測試 -->
<bean id="user" class="com.lyu.spring.entity.User"></bean>

<!-- 註冊jdbc實現的dao -->
<bean id="userDaoJdbc" class="com.lyu.spring.dao.impl.UserDaoJdbc"></bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

問題四:如果有多個構造方法,每個構造方法只有引數的順序不同,那通過構造方法注入多個引數會注入到哪一個呢?

public class UserService implements IUserService {

    private IUserDao userDao;
    private User user;

    public UserService(IUserDao userDao, User user) {
        System.out.println("這是第二個構造方法");
        this.userDao = userDao;
        this.user = user;
    }

    public UserService(User user, IUserDao userDao) {
        System.out.println("這是第一個構造方法");
        this.userDao = userDao;
        this.user = user;
    }

    public void loginUser() {
        userDao.loginUser();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

結果:哪個構造方法在前就注入哪一個,這種情況下就與構造方法順序有關。

這裡寫圖片描述

setter注入

配置檔案如下:

<!-- 註冊userService -->
<bean id="userService" class="com.lyu.spring.service.impl.UserService">
    <!-- 寫法一 -->
    <!-- <property name="UserDao" ref="userDaoMyBatis"></property> -->
    <!-- 寫法二 -->
    <property name="userDao" ref="userDaoMyBatis"></property>
</bean>

<!-- 註冊mybatis實現的dao -->
<bean id="userDaoMyBatis" class="com.lyu.spring.dao.impl.UserDaoMyBatis"></bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

注:上面這兩種寫法都可以,spring會將name值的每個單詞首字母轉換成大寫,然後再在前面拼接上”set”構成一個方法名,然後去對應的類中查詢該方法,通過反射呼叫,實現注入。

切記:name屬性值與類中的成員變數名以及set方法的引數名都無關,只與對應的set方法名有關,下面的這種寫法是可以執行成功的

public class UserService implements IUserService {

    private IUserDao userDao1;

    public void setUserDao(IUserDao userDao1) {
        this.userDao1 = userDao1;
    }

    public void loginUser() {
        userDao1.loginUser();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

還有一點需要注意:如果通過set方法注入屬性,那麼spring會通過預設的空參構造方法來例項化物件,所以如果在類中寫了一個帶有引數的構造方法,一定要把空引數的構造方法寫上,否則spring沒有辦法例項化物件,導致報錯。 
這裡寫圖片描述

基於註解的注入

在介紹註解注入的方式前,先簡單瞭解bean的一個屬性autowire,autowire主要有三個屬性值:constructor,byName,byType。

  • constructor:通過構造方法進行自動注入,spring會匹配與構造方法引數型別一致的bean進行注入,如果有一個多引數的構造方法,一個只有一個引數的構造方法,在容器中查詢到多個匹配多引數構造方法的bean,那麼spring會優先將bean注入到多引數的構造方法中。

  • byName:被注入bean的id名必須與set方法後半截匹配,並且id名稱的第一個單詞首字母必須小寫,這一點與手動set注入有點不同。

  • byType:查詢所有的set方法,將符合符合引數型別的bean注入。


下面進入正題:註解方式註冊bean,注入依賴 

主要有四種註解可以註冊bean,每種註解可以任意使用,只是語義上有所差異:

  1. @Component:可以用於註冊所有bean
  2. @Repository:主要用於註冊dao層的bean
  3. @Controller:主要用於註冊控制層的bean
  4. @Service:主要用於註冊服務層的bean

描述依賴關係主要有兩種:

  • @Resource:java的註解,預設以byName的方式去匹配與屬性名相同的bean的id,如果沒有找到就會以byType的方式查詢,如果byType查詢到多個的話,使用@Qualifier註解(spring註解)指定某個具體名稱的bean。
@Resource
@Qualifier("userDaoMyBatis")
private IUserDao userDao;

public UserService(){

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • @Autowired:spring註解,預設也是以byName的方式去匹配與屬性名相同的bean的id,如果沒有找到,就通過byType的方式去查詢,如果查詢到多個,用@Qualifier註解限定具體使用哪個。
@Autowired
@Qualifier("userDaoJdbc")
private IUserDao userDao;
  • 1
  • 2
  • 3

相關推薦

Spring 依賴注入方式的實現,及迴圈依賴問題的解決(原始碼+XML配置)

搬磚啦,搬磚啦,這幾天在看Spring相關的書,下面給大家分享一下這幾天的心得與收穫,Go Go Go! Spring支援兩種依賴注入方式,分別是屬性注入,建構函式注入。除此之外,Spring還支援工廠注入方式。 接下來,我們一起來了解一下Spring的幾種注入方式。

AndroidStudio中新增依賴方式以及如何引入so檔案和arr檔案

轉載自:http://blog.csdn.net/zxc514257857/article/details/56534863 前言   AndroidStudio中新增依賴的三個選項,如圖:   分別為:庫依賴(Library dependency)、檔案依賴(

面試中被問Spring循環依賴方式!!!

caused 源碼 dsi tail 依賴 移除 order all 錯誤 什麽是循環依賴? 循環依賴其實就是循環引用,也就是兩個或則兩個以上的 Bean 互相持有對方,最終形成閉環。比如A依賴於B,B依賴於C,C又依賴於A。如下圖: 如果在日常開發中我們用new 對象的

面試中被問Spring迴圈依賴方式!!!

什麼是迴圈依賴? 迴圈依賴其實就是迴圈引用,也就是兩個或則兩個以上的 Bean 互相持有對方,最終形成閉環。比如A依賴於B,B依賴於C,C又依賴於A。如下圖: 如果在日常開發中我們用new 物件的方式發生這種迴圈依賴的話程式會在執行時一直迴圈呼叫,直至記憶體溢位報錯。下面說一下Spring是如果解決迴

Spring 依賴注入方式

紙上得來終覺淺 1.構造器注入 AnimalDao: package com.roadArchitectWeb.dao; public interface AnimalDao { /*所有動物有一個說話的方法*/ public void say(); } CatDao

依賴注入(Dependency Injection)的方式

為了對程式碼進行簡化,在得到dao時不必每次都寫出拿到dao的方法,可以使用依賴注入的方式. 依賴注入有2種方式: 1.基於setXX的方式:判斷有無setXX的方法,如果有,則將xx物件注入 具體程式碼: public static void diDao(Object o

依賴注入方式

Spring通過DI(依賴注入)實現IOC(控制反轉),常用的注入方式主要有三種:構造方法注入,setter注入,基於註解的注入。構造方法注入先簡單看一下測試專案的結構,用maven構建的,四個包:entity:儲存實體,裡面只有一個User類dao:資料訪問,一個介面,兩個

【SSH三大框架】Spring基礎第二篇:Spring依賴注入方式

控制反轉(Inversion of Control)和依賴注入(Dependency Injection):應用控制反轉,物件在被建立的時候,由一個調控系統內所有物件的外界實體將其所依賴的物件的引用傳遞給它。也可以說,依賴被注入到物件中。所以,控制反轉是,關於一個物件如何獲

Spring依賴注入方式

Spring支援兩種依賴注入方式,分別是屬性注入和建構函式注入。除此之外,Spring還支援工廠方法注入。 1.屬性注入 實體類Car,有三個屬性 public class Car { private int maxSpeed; pr

IOC與DI的講解以及依賴注入方式

首先:第一個問題,參與者都有誰?1)物件2)IOC/DI容器3)某個物件的外部資源第二問題:依賴,誰依賴誰?為什麼需要依賴?依賴嘛,很好理解的,物件依賴於IOC/DI容器,至於為什麼要依賴呢?物件需要IOC/DI容器來提供物件需要的外部資源。第三個問題:注入,誰注入誰?又注入了什麼呢?顯而易見是IOC/DI容

Spring靜態注入方式

Spring靜態注入的三種方式: (說明:MongoFileOperationUtil是自己封裝的一個Mongodb檔案讀寫工具類,裡面需要依賴AdvancedDatastore物件例項,dsForRW用來獲取Mongodb資料來源) 在springframework裡,我們不能@Autowir

spring注入bean的方式

1、自動化裝配bean 元件裝配:Spring會自動發現應用上下文所建立的bean。 自動裝配:Spring自動滿足bean之間的依賴 在類上加入@Component註解,告訴spring為這個類建立bean 使用@Autowired註解實現自動裝配,也可以使用java規範的@Inj

Spring boot 梳理 - SpringBoot中注入ApplicationContext物件的方式

直接注入(Autowired) @Configuration public class OAConfig { @Autowired private ApplicationContext applicationContext; @B

Spring Spring 靜態屬性 注入方式

Spring靜態注入的三種方式: (說明:MongoFileOperationUtil是自己封裝的一個Mongodb檔案讀寫工具類,裡面需要依賴AdvancedDatastore物件例項,dsForRW用來獲取Mongodb資料來源) 在springframewo

springboot物件注入IOC容器的方式

Springboot會自動載入resources檔案下面的application.yml或者application.properties配置檔案,因為yml格式可以替代xml格式,功能properties更強大,所以一般都使用yml格式進行書寫。 1.對於yml中載入了的b

BeanFactory和它的物件註冊和依賴繫結的方式

一、Spring中的BeanFactory是什麼?   BeanFactory是個基本的IoC容器,提供完整的IoC服務支援,負責物件建立的管理和依賴注入服務   如果沒有特殊指定,預設採用延遲初始化策略(lazy-load)。只有當客戶端物件需要訪問容器中的某個受管物件

AndroidStudio 新增依賴方式

方法一 直接從maven庫新增 repositories { maven { url '********************' } } dependencies { // Type 1: depend on maven server version im

Spring定義bean的方式和自動注入

前言:隨著一個專案規模的增大,我們不得不引入許多Java bean物件,而這些物件一般來說是在Spring的配置檔案applicationContext.xml中進行配置的,這樣就聲明瞭這是一個由Spring容器管理的bean物件。這種做法必然會導致Spring的配置檔案的

SpringBoot中注入ApplicationContext物件的方式

在專案中,我們可能需要手動獲取spring中的bean物件,這時就需要通過 ApplicationContext 去操作一波了! 1、直接注入(Autowired) @Component public class User { @Aut

Spring實現控制反轉(IOC)的方式(一)——屬性注入

這篇文章,來理解一下Spring IOC的屬性注入(set注入)方法。還是用上一篇的程式設計師寫程式碼的例子。 package com.spring.demo02.entity; public class Programmer { private String n