天天看點

手把手教你使用 Spring IOC 容器完成注入操作(xml注入 + 注解注入)

Spring IOC 容器的基本使用

一、為什麼要使用 Spring?

1.1 傳統的 MVC 架構的程式1.2 程式耦合性過高?1.3 如何解耦?1.4 Spring IOC 的依賴注入

  • 二、Spring IOC 的依賴注入(使用 xml 完成注入)
  • 2.1 使用構造函數完成依賴注入
  • 2.1.1 标簽的使用講解
  • 2.1.2 構造函數依賴注入的優缺點
  • 2.1.3 使用構造函數完成依賴注入的執行個體
  • 2.2 使用 setter 完成注入
  • 2.2.1 使用 setter 完成依賴注入的功能
  • 2.2.2 基于 setter 完成依賴注入的分析
  • 2.2.3 基于 setter 注入的簡化操作
  • 2.3 複雜資料類型注入
  • 2.3.1 集合資料類型注入使用場景
  • 2.3.2 集合類型的資料注入
  • 三、使用注解完成 Spring 的 IOC 注入
  • 3.1 用于建立對象的注解
  • 3.1.1 普通方法建立對象
  • 3.1.2 Componet 注解(還有和它功能一樣的三層注解)
  • 3.2 用于注入資料的注解
  • 3.2.1 資料方式剖析
  • 3.2.2 注入方式一(Autowired + Qualifier)
  • 3.2.3 基于 Resource 的注解
  • 四、Spring IOC 注入總結

本文的代碼過多,但是每個點我會盡可能的寫的很詳細

一、為什麼要使用 Spring?

1.1 傳統的 MVC 架構的程式

我們平時編寫一個小項目的時候,一般會采用 MVC 三層架構來編寫一個項目

  • M —— modal 模型層(實體類)
  • V —— views 視圖層 (界面)
  • C —— controller 控制層 (用來完執行一些操作)

這三層架構各自分工,獨自完成相對應的功能,但是這樣的程式寫出來會導緻程式之間耦合性過高

1.2 程式耦合性過高?

耦合性過高實際上說的是程式之間的依賴性過高,解耦說的就是降低程式之間的依賴關系

我們使用 Java 通常都是寫好一個類,構造方法,setter 和 getter 等等,我們在其他的類中使用該類就得 建立一個 該類的對象,然後通過對象調用該類的各種方法。這樣整個程式之間就會産生多個類,對應的也會産生多個對象互相進行調用,是以我們整體的程式就會展現出耦合性過高的特點。

1.3 如何解耦?

  1. 我們在 Java SE 中學習過 JDBC,也學習過 properties 對象, 我們可以把 jdbc 的一些配置寫進檔案中。
  2. 我們傳統一般都是建立對象,我們可以換一種方式,通過 Java 的反射機制擷取類的資訊,并且建立對象
  3. 讀取 xml 檔案

1.4 Spring IOC 的依賴注入

Spring 架構正式為了解決這樣的情況出現了,它提供了 讀取 xml配置,以及注解 兩種方式實作 bean 的自動注入,而被注入的容器叫做 IOC 容器

依賴注入:
        Dependency Injection
    IOC 的作用:
        降低程式鍵的耦合(依賴關系)
    依賴關系的管理:
       以後都交給 spring 來維護
       在目前類需要用到其他類的對象,由Spring來為我們提供,我們隻需要在配置檔案中說明

     依賴關系的維護:
            就稱為依賴注入
     依賴注入:
            能注入的資料,有三類
                基本類型和 string
                其他 bean 類型(在配置檔案中或者注解配置過的 bean—)
                複雜類型、集合類型

            注入的方式:有三種
                第一種:使用構造函數提供
                第二種:使用 set方法提供
                第三種:使用注解提供      

二、Spring IOC 的依賴注入(使用 xml 完成注入)

2.1 使用構造函數完成依賴注入

2.1.1 标簽的使用講解

  • 使用的标簽:constructor-arg
  • 标簽出現的位置:bean标簽的内部
  • 标簽中的屬性 1. type:用于指定要注入的資料的資料類型,該資料類型可以是構造函數中某個或某些參數的類型 2. index: 用于指定要注入的資料給構造函數中指定索引位置的參數指派,索引的位置也是從 0 開始 3. name:用于指定構造函數中指定名稱的參數指派以上三個标簽用于指定給構造函數中哪個參數指派 5. value: 用于給基本類型和 String類型的資料 6. ref:用于指定其它的 bean 類型資料,它指的就是 spring IOC 核心容器中出現過的 bean 對象

2.1.2 構造函數依賴注入的優缺點

  • 優勢: 在擷取 bean 對象時,注入資料是必須的操作,否則對象無法建立成功
  • 弊端: 改變了bean 對象的執行個體化方式,使我們在建立對象時,如果用不到,也必須建立

2.1.3 使用構造函數完成依賴注入的執行個體

注意:後面的修改全部都是基于此類的修改在這裡插入代碼片

  1. 編寫 bean.xml 配置檔案
  2. 編寫一個 AccountService 接口,後面的三種方法都要實作該接口
  3. 編寫 AccountServiceImpl 實作該接口,并且記住該類的名稱和位置
  4. 編寫一個 Client 類,用來測試該接口中的方法

bean.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- 使用構造函數注入
         使用的标簽:constructor-arg
         标簽出現的位置:bean标簽的内部
         标簽中的屬性
            type:用于指定要注入的資料的資料類型,該資料類型可以是構造函數中某個或某些參數的類型
            index: 用于指定要注入的資料給構造函數中指定索引位置的參數指派,索引的位置也是從 0 開始
            name:用于指定構造函數中指定名稱的參數指派
            ============== 以上三個用于指定給構造函數中哪個參數指派 ============
            value: 用于給基本類型和 String類型的資料
            ref:用于指定其它的 bean 類型資料,它指的就是 spring IOC 核心容器中出現過的 bean 對象

            優勢:
                在擷取 bean 對象時,注入資料是必須的操作,否則對象無法建立成功
            弊端:
                改變了bean 對象的執行個體化方式,使我們在建立對象時,如果用不到,也必須建立
      -->
     <!-- 方式1 -->
    <bean id="accountService" class="com.itheima.service.impl.IAccountServceImpl">
        <constructor-arg name="name" value="text"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg name="birthday"  ref="now"></constructor-arg>
    </bean>

    <!-- 方式2  下标形,根據有參的構造函數的位置,填寫對應的數值 -->
    <bean id="accountService1" class="com.itheima.service.impl.IAccountServceImpl">
        <constructor-arg index="0" value="text"></constructor-arg>
        <constructor-arg index="1" value="18"></constructor-arg>
        <constructor-arg index="2"  ref="now"></constructor-arg>
    </bean>

    <!-- 方式3, 使用 type 指定參數類型,進行構造傳入 -->
     <bean id="accountService,2" class="com.itheima.service.impl.IAccountServceImpl">
        <constructor-arg type="java.lang.String" value="text"></constructor-arg>
        <constructor-arg type="java.lang.Integer" value="18"></constructor-arg>
        <constructor-arg type="java.util.Date"  ref="now"></constructor-arg>
    </bean>

    <!-- bean 中的 ref 一般指向一個對象  配置一個日期對象,上面會引用到 now   -->
    <bean id="now" class="java.util.Date"></bean>
</beans>      

IAccountService 接口編寫

package com.itheima.service;

public interface IAccountService {
    void saveAccount();
}      

IAccountServceImpl 接口實作類的編寫

package com.itheima.service.impl;

import com.itheima.service.IAccountService;
import java.util.Date;

/**
 * 賬戶業務層的實作類
 * 構造函數的注入
 * */
public class IAccountServceImpl implements IAccountService {
    // 經常變化的資料,并不适用于注入的方式
    private  String name;
    private  Integer age;
    private Date birthday;

    // 建立有參的構造方法,這個方法必須存在, 在xml中,資料就是通過有參的構造方法擦混入的
    public IAccountServceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public  IAccountServceImpl() {
        System.out.println("對象建立了");
    }

    public void saveAccount() {
        System.out.println("service 中的 saveAccount 方法執行了"+this.name + " "+ this.age + " " + this.birthday);
    }

    @Override
    public String toString() {
        return "IAccountServceImpl{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                '}';
    }
}      

Client 類的編寫

package com.itheima.client;

import com.itheima.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 模拟一個表現層,用于調用業務層
 * */
public class Client {

    public static void main(String[] args) {
        // 使用 mvc 三層架構,編寫 (耦合性過高)
        // IAccountService as = new IAccountServceImpl(); 

        // =============== 劃重點 ===============
        // 1. 擷取核心容器對象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//        ApplicationContext ac = new FileSystemXmlApplicationContext("xxx"); // 這裡填寫配置檔案,在你本機上的實體位址,很少使用者

        // 2. 根據 id 擷取 Bean 對象 (方式一)
        IAccountService as = (IAccountService) ac.getBean("accountService");
        System.out.println(as);
        as.saveAccount();

        //2. 根據 id 擷取 Bean 對象 (方式二)
//        IAccountDao adao = ac.getBean("accountDao", IAccountDao.class);
//        as.saveAccount();
//        System.out.println(adao);
    }
}      

運作結果:

我們沒有使用 傳統的方式,接用 Spring 架構完成了 bean 的執行個體化

手把手教你使用 Spring IOC 容器完成注入操作(xml注入 + 注解注入)

2.2 使用 setter 完成注入

2.2.1 使用 setter 完成依賴注入的功能

涉及的标簽:property
    出現的位置:bean 标簽的内部
    标簽的屬性:
    name:用于指定注入時所用的 set 方法名稱

    == 以上三個用于指定給構造函數中哪個參數指派 ==

    value: 用于給基本類型和 String類型的資料
    ref:用于指定其它的 bean 類型資料,它指的就是 spring IOC 核心容器中出現過的 bean 對象      

2.2.2 基于 setter 完成依賴注入的分析

  • 優勢: 建立對象時沒有明确的限制,可以直接使用預設構造函數
  • 弊端: 如果某個成員必須有值,則擷取對象可能 set 方法沒有執行

有了前面的内容做鋪墊,接下來做 setter 注入就會輕松很多,我們需要做如下步驟

  1. 在 bean.xml 添加依賴
<!-- setter 方法注入
        涉及的标簽:property
        出現的位置:bean 标簽的内部
        标簽的屬性:
        name:用于指定注入時所用的 set 方法名稱

        ============== 以上三個用于指定給構造函數中哪個參數指派 ============
        value: 用于給基本類型和 String類型的資料
        ref:用于指定其它的 bean 類型資料,它指的就是 spring IOC 核心容器中出現過的 bean 對象
        優勢:
            建立對象時沒有明确的限制,可以直接使用預設構造函數
        弊端:
            如果某個成員必須有值,則擷取對象可能 set 方法沒有執行
     -->

    <bean class="com.itheima.service.impl.IAccountServiceImpl2" id="accountService2">
        <property name="name" value="小紅"></property>
        <property name="age" value="19"></property>
        <property name="birthday" value="2000/4/12"></property>
    </bean>      
  1. 編寫 IAccountServiceImpl2
package com.itheima.service.impl;

import com.itheima.service.IAccountService;

import java.util.Date;

/**
 * setter 注入
 * */
public class IAccountServiceImpl2 implements IAccountService {
    private String name;
    private Integer age;
    private Date birthday;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "IAccountServiceImpl2{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                '}';
    }

    public void saveAccount() {
        System.out.println("service 中的 saveAccount 方法執行了");
    }
}      
  1. Client 内容修改
package com.itheima.client;

import com.itheima.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 模拟一個表現層,用于調用業務層
 * */
public class Client {

    public static void main(String[] args) {
        // 1. 擷取核心容器對象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

        // 2. 根據 id 擷取 Bean 對象 (兩種方式)
        IAccountService as = (IAccountService) ac.getBean("accountService2");
        System.out.println(as);
        as.saveAccount();

    }
}      
  1. 效果圖(資料成功通過 setter 注入)
    手把手教你使用 Spring IOC 容器完成注入操作(xml注入 + 注解注入)

2.2.3 基于 setter 注入的簡化操作

限制新增 p 标簽

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- javabean 提供:路徑,屬性設定 -->
    <!-- setter 注入一個 bean -->
    <bean id="person" class="cn.gorit.entity.Person">
        <property name="name" value="小黃"></property>
        <property name="gender" value=""></property>
        <property name="age" value="18"></property>
    </bean>

    <!-- setter 使用 p 标簽簡化注入操作 -->
    <bean id="person1" class="cn.gorit.entity.Person" p:name="小黃" p:gender="男" p:age="19"/>

</beans>      

2.3 複雜資料類型注入

2.3.1 集合資料類型注入使用場景

複雜類型的注入,集合類型的注入
    常用 list 和 map
    用于給 List 結構集合注入的标簽
        list array set
    用于給 Map 結構集合注入的标簽
        map props
    結構相同,标簽可以互換      

2.3.2 集合類型的資料注入

  1. bean.xml 的配置
<!--
    複雜類型的注入,集合類型的注入
        常用 list 和 map
        用于給 List 結構集合注入的标簽
            list array set
        用于給 Map 結構集合注入的标簽
            map props
        結構相同,标簽可以互換

            IOC 内容結束
    -->
    <bean id="accountService3" class="com.itheima.service.impl.IAccountServiceImpl3">
        <!-- 字元串注入 -->
        <property name="myStrs">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>

        <!-- 集合 List 的注入 -->
        <property name="myList">
            <list>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </list>
        </property>

        <!-- 集合 Set 注入--> 
        <property name="mySet">
            <set>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </set>
        </property>

        <!-- Map 注入 -->
        <property name="myMap">
            <map>
                <entry key="testA" value="aaa"></entry>
                <entry key="testB">
                    <value>BBB</value>
                </entry>
            </map>
        </property>

        <!-- Properties 注入-->
        <property name="myPros">
            <props>
                <prop key="testC">CCC</prop>
                <prop key="testD">DDD</prop>
            </props>
        </property>
    </bean>      
  1. IAccountServiceImpl3 編寫
package com.itheima.service.impl;

import com.itheima.service.IAccountService;

import java.util.*;

public class IAccountServiceImpl3 implements IAccountService {
    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String,String> myMap;
    private Properties myPros;

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public void setMyPros(Properties myPros) {
        this.myPros = myPros;
    }

    public void saveAccount() {
        System.out.println(Arrays.toString(myStrs));
        System.out.println(myList);
        System.out.println(mySet);
        System.out.println(myMap);
        System.out.println(myPros);
    }

    @Override
    public String toString() {
        return "IAccountServiceImpl3{" +
                "myStrs=" + Arrays.toString(myStrs) +
                ", myList=" + myList +
                ", mySet=" + mySet +
                ", myMap=" + myMap +
                ", myPros=" + myPros +
                '}';
    }
}      
  1. Client 編寫
package com.itheima.client;

import com.itheima.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {

    public static void main(String[] args) {
        // 1. 擷取核心容器對象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

        // 2. 根據 id 擷取 Bean 對象 (兩種方式)
        IAccountService as = (IAccountService) ac.getBean("accountService3");

        System.out.println(as);
        as.saveAccount();
    }
}      
  1. 效果圖
    手把手教你使用 Spring IOC 容器完成注入操作(xml注入 + 注解注入)

三、使用注解完成 Spring 的 IOC 注入

bean.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">

        <!--  使用注解來實作注入  -->

        <!--  告知 spring 在建立容器時要掃描的包,配置所需要的标簽不是  在 beans 限制中,而是一個名為 context
              名稱空間和限制中( 一個标簽 + 注解的方式完成 IOC 注入)-->
        <context:component-scan base-package="com.itheima"></context:component-scan>

</beans>      

編寫 IAccountService 接口

package com.itheima.service;

public interface IAccountService {
    void saveAccount();
}      

編寫 IAccountDao 接口

package com.itheima.dao;

/**
 * 賬戶持久層接口
 * */
public interface IAccountDao {
    /**
     * 模拟儲存賬戶
     * */
    void saveAccount();
}      

3.1 用于建立對象的注解

我們在這裡實作 IAccountService 接口 建立 IAccountServiceImpl類

3.1.1 普通方法建立對象

package com.itheima.service.impl;

/*   曾經的 xml 配置,我們要在這裡協商這麼一大段的 xml 才可以完成注入
 *  <bean id="accountService"
 *      class="com.itheima.service.impl.IAccountServceImpl
 *      <property name="" value="" | ref =""></property>
 *     "/>
 */

import com.itheima.service.IAccountService;
import com.itheima.dao.IAccountDao;

public class IAccountServiceImpl implements IAccountService {
    //1、 采用 new 建立對象,在外面還是需要通過類來建立對象解決
    private IAccountDao accountDao = new IAccountDaoImpl();

    public IAccountServiceImpl() {
        System.out.println("對象建立了");
    }

    public void saveAccount() {
        int i =1;
        accountDao.saveAccount();
        System.out.println(i);
        i++;
    }
    @Override
    public String toString() {
        return "IAccountServiceImpl{" +
                "accountDao=" + accountDao +
                '}';
    }
}      

3.1.2 Componet 注解(還有和它功能一樣的三層注解)

和它功能相同的還有

  1. Controller: 一般用在表現層
  2. Service: 一般用在業務層
  3. Respository: 一般用在持久層
三層注解的解讀:
 * 用于建立對象的注解
 *     他們的作用就和在 XML 配置檔案中編寫一個 <bean> 标簽實作的功能是一樣的
 *     @Componet
 *              作用:用于把目前類對象存入spring 容器中
 *              屬性:
 *                  value 用于指定 bean 的 id,當我們不寫時,它的預設是目前類名,(AccountService  => accountService)
 *                  我的是兩個首字母都是大寫,是以不用改 IAccountServceImpl
 *      Controller: 一般用在表現層
 *      Service: 一般用在業務層
 *      Respository: 一般用在持久層
 *      以上三個注解的作用和屬性與 Component 是一模一樣的,
 *      他們三個是 spring 架構為我們提供明确的三層使用的注解,使我們三層對象更加清晰      

他們的用法都是一樣的,如下

實作: IAccountService 接口

package com.itheima.service.impl;

import com.itheima.service.IAccountService;
import com.itheima.dao.IAccountDao;
import org.springframework.stereotype.Component;

@Component(value = "accountService") 
//@Service(value = "accountService")  // 該注解和上面的注解功能是一模一樣的,隻是用來區分使用情景的,如果有兩個注解,則 value 不能省去
public class IAccountServiceImpl implements IAccountService {
    // 這裡的值為空,等會可以看到,因為我們隻是通過 Spring 建立了對象,但是并沒有把對象注入
    private IAccountDao accountDao;

    public void saveAccount() {
        int i =1;
        System.out.println(i);
        i++;
    }

    @Override
    public String toString() {
        return "IAccountServiceImpl{" +
                "accountDao=" + accountDao +
                '}';
    }
}      

實作:IAccountDao 接口

package com.itheima.dao.impl;

import com.itheima.dao.IAccountDao;
import org.springframework.stereotype.Repository;

/**
 * 賬戶持久層的實作類
 * */
@Repository("accountDao") // 該注解功能同 Componet ,使用在持久層
public class IAccountDaoImpl implements IAccountDao {
    /**
     * 模拟儲存賬戶
     */
    public void saveAccount() {
       System.out.println("儲存了賬戶");
    }

    @Override
    public String toString() {
        return "IAccountDaoImpl{}";
    }
}      

建立 Client 類

package com.itheima.client;

import com.itheima.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


/**
 * 模拟一個表現層,用于調用業務層
 * */
public class Client {
    /**
     * 擷取 spring 的 Ioc 核心容器,并根據 id 擷取對象
     * ApplicationCpmtext 的三個常用實作類
     *      ClassPathXMLApplicationContext:它可以加載類路徑下的配置檔案,要求配置檔案必須在類路徑下,不在的話,加載不了
     *      FileSystemXmlApplicationContext:它可以加載磁盤任意路徑下的配置檔案(必須有通路權限)
     *      AnnotationConfigApplicationContext:它是用于讀取注解解耦容器的
     *
     * 核心容器的兩個接口引發出的問題
     *   ApplicationContext:單例  采用此接口
     *      它在建構核心容器時,建立對象采用的政策是利用加載的方式,也就是說,隻要一讀取完配置檔案馬上就建立配置檔案中的配置對象
     *   BeanFactory: 多例
     *      它在建構核心容器時:建立對象采取的政策是采用延遲加載的方式。也就是說,什麼時候根據 id 擷取對象了,什麼時候才真正的建立對象
     * */
    public static void main(String[] args) {

        // 1. 擷取核心容器對象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        // 2. 根據 id 擷取 Bean 對象 (兩種方式)
        IAccountService as = (IAccountService) ac.getBean("accountService");
        System.out.println(as);
        as.saveAccount();
    }
}      

運作結果:

(因為我并沒有進行對象注入,是以這裡的值為 null)

手把手教你使用 Spring IOC 容器完成注入操作(xml注入 + 注解注入)

3.2 用于注入資料的注解

3.2.1 資料方式剖析

*      他們的作用就和在 xml 配置檔案中的 bean 标簽寫一個 <property>标簽的作用是一樣的
 *      Autowired:
 *          作用:自動按照類型注入。隻要容器中有唯一的 bean 對象類型和要注入的變量類型比對,就可以注入成功
 *                如果 IOC 容器中沒有任何 bean 的類型和要注入的變量類型比對,則報錯
 *                如果 IOC 容器中有多個類型比對時
 *          出現位置:
 *              可以是變量上,也可以是方法上
 *          細節:
 *              在使用注解注入時,set 方法就不是必須的了。
 *       Qualifier:
 *             作用:在按照類中注入的基礎之上再按照名稱注入,它在給類成員注入時不能單獨使用,但是再給方法參數注入時可以使用
 *             屬性:
 *                  value: 用于指定注入的 bean 的 id
 *             補充:必須和 Autowired 一起使用
 *       Resource
 *              作用:直接按照 Bean 的id 注入,它可以獨立使用 (一個搞定上面兩個)
 *              屬性:
 *                  name:用于指定 bean 的id      

3.2.2 注入方式一(Autowired + Qualifier)

重新編寫

package com.itheima.service.impl;

/*      注入方式一
 *      Autowired:
 *          作用:自動按照類型注入。隻要容器中有唯一的 bean 對象類型和要注入的變量類型比對,就可以注入成功
 *                如果 IOC 容器中沒有任何 bean 的類型和要注入的變量類型比對,則報錯
 *                如果 IOC 容器中有多個類型比對時
 *          出現位置:
 *              可以是變量上,也可以是方法上
 *          細節:
 *              在使用注解注入時,set 方法就不是必須的了。
 *       Qualifier:
 *             作用:在按照類中注入的基礎之上再按照名稱注入,它在給類成員注入時不能單獨使用,但是再給方法參數注入時可以使用
 *             屬性:
 *                  value: 用于指定注入的 bean 的 id
 *             補充:必須和 Autowired 一起使用
*/

import com.itheima.service.IAccountService;
import com.itheima.dao.IAccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Service(value = "accountService")  // 看 Component
public class IAccountServiceImpl implements IAccountService {

    // 2、 采用注解的方式
    @Autowired
    @Qualifier("accountDao")
    private IAccountDao accountDao;

    public void saveAccount() {
        int i =1;
//        accountDao.saveAccount();
        System.out.println(i);
        i++;
    }

    @Override
    public String toString() {
        return "IAccountServiceImpl{" +
                "accountDao=" + accountDao +
                '}';
    }
}      

運作效果

3.2.3 基于 Resource 的注解

四、Spring IOC 注入總結

  1. 首先在配置檔案中加入:<context:component-scan base-package="com.itheima"></context:component-scan>​,告知 Spring,我們要使用注解,然後我們在裡面填寫:base-package 的值,告知 Spring 他要掃描的包
  2. 然後在接口的實作類中的類上添加注解(建立對象的注入):@Component(value = "accountService") 并指定其 value,(如果命名規範的話,比如我寫的是 AccountService,預設值也就是上面的 value值),即可完成建立對象的操作,如果想劃分的更細一點,可以使用如下三種注解,劃分功能
  1. @Controller: 一般用在表現層
  2. @Service: 一般用在業務層
  3. @Respository: 一般用在持久層
  1. 然後在類相對應的方法,完成資料的注入,使用兩種方法都可以
  1. @Autowired + @Qualifier(“accountDao”) 完成對象的注入
  2. @Resource(name = “accountDao”) 完成對象的注入