Spring框架 第2章 IOC容器和Bean的配置

?

第2章 ?IOC容器和Bean的配置

2.1 IOC和DI

2.1.1 IOC(Inversion of Control):反轉(zhuǎn)控制

在應(yīng)用程序中的組件需要獲取資源時(shí),傳統(tǒng)的方式是組件主動(dòng)的從容器中獲取所需要的資源,在這樣的模式下開發(fā)人員往往需要知道在具體容器中特定資源的獲取方式,增加了學(xué)習(xí)成本,同時(shí)降低了開發(fā)效率。

反轉(zhuǎn)控制的思想完全顛覆了應(yīng)用程序組件獲取資源的傳統(tǒng)方式:反轉(zhuǎn)了資源的獲取方向——改由容器主動(dòng)的將資源推送給需要的組件,開發(fā)人員不需要知道容器是如何創(chuàng)建資源對象的,只需要提供接收資源的方式即可,極大的降低了學(xué)習(xí)成本,提高了開發(fā)的效率。這種行為也稱為查找的被動(dòng)形式。

2.1.2 DI(Dependency Injection):依賴注入

IOC的另一種表述方式:即組件以一些預(yù)先定義好的方式(例如:setter 方法)接受來自于容器的資源注入。相對于IOC而言,這種表述更直接。

2.1.3 IOC容器在Spring中的實(shí)現(xiàn)

1)在通過IOC容器讀取Bean的實(shí)例之前,需要先將IOC容器本身實(shí)例化。

2)Spring提供了IOC容器的兩種實(shí)現(xiàn)方式

① BeanFactory:IOC容器的基本實(shí)現(xiàn),是Spring內(nèi)部的基礎(chǔ)設(shè)施,是面向

Spring本身的,不是提供給開發(fā)人員使用的。

② ApplicationContext:BeanFactory的子接口,提供了更多高級特性。面向Spring的使用者,幾乎所有場合都使用ApplicationContext而不是底層的BeanFactory。

2.1.4 ApplicationContext的主要實(shí)現(xiàn)類

? 1)? ClassPathXmlApplicationContext:對應(yīng)類路徑下的XML格式的配置文件

? 2)? FileSystemXmlApplicationContext:對應(yīng)文件系統(tǒng)中的XML格式的配置文件

? 3)? 在初始化時(shí)就創(chuàng)建單例的bean,也可以通過配置的方式指定創(chuàng)建的Bean是多實(shí)例的。

2.1.5 ConfigurableApplicationContext

? 1)? 是ApplicationContext的子接口,包含一些擴(kuò)展方法

? 2)? refresh()和close()讓ApplicationContext具有啟動(dòng)、關(guān)閉和刷新上下文的能力。

2.1.6 WebApplicationContext

? 1)? 專門為WEB應(yīng)用而準(zhǔn)備的,它允許從相對于WEB根目錄的路徑中完成初始化工作

2.2 通過類型獲取bean

? 1)? 從IOC容器中獲取bean時(shí),除了通過id值獲取,還可以通過bean的類型獲取。但如果同一個(gè)類型的bean在XML文件中配置了多個(gè),則獲取時(shí)會拋出異常,所以同一個(gè)類型的bean在容器中必須是唯一的。

HelloWorld helloWorld = cxt.getBean(HelloWorld.?class);

? 2)? 或者可以使用另外一個(gè)重載的方法,同時(shí)指定bean的id值和類型

HelloWorld helloWorld = cxt.getBean(“helloWorld”,HelloWorld.?class);

2.3 給bean的屬性賦值

2.3.1 依賴注入的方式

1. 通過bean的setXxx()方法賦值

Hello World中使用的就是這種方式

2. 通過bean的構(gòu)造器賦值

? 1)? Spring自動(dòng)匹配合適的構(gòu)造器? 2)? 通過索引值指定參數(shù)位置??

 

? 3)? 通過類型區(qū)分重載的構(gòu)造器

2.3.2 ?p名稱空間

為了簡化XML文件的配置,越來越多的XML文件采用屬性而非子元素配置信息。Spring 從2.5版本開始引入了一個(gè)新的p命名空間,可以通過<bean>元素屬性的方式配置Bean 的屬性。

使用p命名空間后,基于XML的配置方式將進(jìn)一步簡化。

2.3.3 可以使用的值

1. 字面量

? 1)可以使用字符串表示的值,可以通過value屬性或value子節(jié)點(diǎn)的方式指定

? 2) 基本數(shù)據(jù)類型及其封裝類、String等類型都可以采取字面值注入的方式

? 3)? 若字面值中包含特殊字符,可以使用<![CDATA[]]>把字面值包裹起來

2. null值

3. 給bean的級聯(lián)屬性賦值

4. 外部已聲明的bean

5. 內(nèi)部bean

當(dāng)bean實(shí)例僅僅給一個(gè)特定的屬性使用時(shí),可以將其聲明為內(nèi)部bean。內(nèi)部bean聲明直接包含在<property>或<constructor-arg>元素里,不需要設(shè)置任何id或name屬性

內(nèi)部bean不能使用在任何其他地方

2.4 集合屬性

在Spring中可以通過一組內(nèi)置的XML標(biāo)簽來配置集合屬性,例如:<list>,<set>或<map>。

2.4.1 數(shù)組和List

配置java.util.List類型的屬性,需要指定<list>標(biāo)簽,在標(biāo)簽里包含一些元素。這些標(biāo)簽 可以通過<value>指定簡單的常量值,通過<ref>指定對其他Bean的引用。通過<bean> 指定內(nèi)置bean定義。通過<null/>指定空元素。甚至可以內(nèi)嵌其他集合。

數(shù)組的定義和List一樣,都使用<list>元素。

配置java.util.Set需要使用<set>標(biāo)簽,定義的方法與List一樣。

2.4.2 Map

Java.util.Map通過<map>標(biāo)簽定義,<map>標(biāo)簽里可以使用多個(gè)<entry>作為子標(biāo)簽。每個(gè)條目包含一個(gè)鍵和一個(gè)值。

必須在<key>標(biāo)簽里定義鍵。

因?yàn)殒I和值的類型沒有限制,所以可以自由地為它們指定<value>、<ref>、<bean>或<null/>元素。

可以將Map的鍵和值作為<entry>的屬性定義:簡單常量使用key和value來定義;bean引用通過key-ref和value-ref屬性定義。

<bean?id="cup"?class="com.atguigu.spring.bean.Cup">

<property?name="bookMap">

<map>

<entry>

<key>

<value>bookKey01</value>

</key>

<ref?bean="book01"/>

</entry>

<entry>

<key>

<value>bookKey02</value>

</key>

<ref?bean="book02"/>

</entry>

</map>

</property>

</bean>

2.4.3 集合類型的bean

如果只能將集合對象配置在某個(gè)bean內(nèi)部,則這個(gè)集合的配置將不能重用。我們需要 將集合bean的配置拿到外面,供其他bean引用。

配置集合類型的bean需要引入util名稱空間

<util:list?id="bookList">

<ref?bean="book01"/>

<ref?bean="book02"/>

<ref?bean="book03"/>

<ref?bean="book04"/>

<ref?bean="book05"/>

</util:list>

 

<util:list?id="categoryList">

<value>編程</value>

<value>極客</value>

<value>相聲</value>

<value>評書</value>

</util:list>

2.5 ?FactoryBean

2.5.1 FactoryBean

Spring中有兩種類型的bean,一種是普通bean,另一種是工廠bean,即FactoryBean。

工廠bean跟普通bean不同,其返回的對象不是指定類的一個(gè)實(shí)例,其返回的是該工 廠bean的getObject方法所返回的對象。

工廠bean必須實(shí)現(xiàn)org.springframework.beans.factory.FactoryBean接口。

<bean?id="product"?class="com.atguigu.spring.bean.ProductFactory">

<property?name="productName"?value="Mp3"?/>

</bean>

2.6 bean的高級配置

2.6.1 配置信息的繼承

1. 背景

查看下面兩個(gè)Employee的配置,其中dept屬性是重復(fù)的。

<bean?id="dept"?class="com.atguigu.parent.bean.Department">

<property?name="deptId"?value="100"/>

<property?name="deptName"?value="IT"/>

</bean>

 

<bean?id="emp01"?class="com.atguigu.parent.bean.Employee">

<property?name="empId"?value="1001"/>

<property?name="empName"?value="Tom"/>

<property?name="age"?value="20"/>

 

<!-- 重復(fù)的屬性值 -->

<property?name="dept"?ref="dept"/>

</bean>

 

<bean?id="emp02"?class="com.atguigu.parent.bean.Employee">

<property?name="empId"?value="1002"/>

<property?name="empName"?value="Jerry"/>

<property?name="age"?value="25"/>

 

<!-- 重復(fù)的屬性值 -->

<property?name="dept"?ref="dept"/>

</bean>

2. 配置信息的繼承

<!-- 以emp01作為父bean,繼承后可以省略公共屬性值的配置 -->

<bean?id="emp02"?parent="emp01">

<property?name="empId"?value="1002"/>

<property?name="empName"?value="Jerry"/>

<property?name="age"?value="25"/>

</bean>

Spring允許繼承bean的配置,被繼承的bean稱為父bean。繼承這個(gè)父bean的bean 稱為子bean

子bean從父bean中繼承配置,包括bean的屬性配置

子bean也可以覆蓋從父bean繼承過來的配置

 

3. 補(bǔ)充說明

父bean可以作為配置模板,也可以作為bean實(shí)例。若只想把父bean作為模板,可以設(shè)置<bean>的abstract 屬性為true,這樣Spring將不會實(shí)例化這個(gè)bean

如果一個(gè)bean的class屬性沒有指定,則必須是抽象bean

并不是<bean>元素里的所有屬性都會被繼承。比如:autowire,abstract等。

也可以忽略父bean的class屬性,讓子bean指定自己的類,而共享相同的屬性配置。 但

此時(shí)abstract必須設(shè)為true。

2.6.2 bean之間的依賴

有的時(shí)候創(chuàng)建一個(gè)bean的時(shí)候需要保證另外一個(gè)bean也被創(chuàng)建,這時(shí)我們稱前面的bean對后面的bean有依賴。例如:要求創(chuàng)建Employee對象的時(shí)候必須創(chuàng)建Department。 這里需要注意的是依賴關(guān)系不等于引用關(guān)系,Employee即使依賴Department也可以不引用它。

<bean?id="emp03"?class="com.atguigu.parent.bean.Employee"?depends-on="dept">

<property?name="empId"?value="1003"/>

<property?name="empName"?value="Kate"/>

<property?name="age"?value="21"/>

</bean>

2.7 ?bean的作用域

在Spring中,可以在<bean>元素的scope屬性里設(shè)置bean的作用域,以決定這個(gè)bean是單實(shí)例的還是多實(shí)例的。

默認(rèn)情況下,Spring只為每個(gè)在IOC容器里聲明的bean創(chuàng)建唯一一個(gè)實(shí)例,整個(gè)IOC容器范圍內(nèi)都能共享該實(shí)例:所有后續(xù)的getBean()調(diào)用和bean引用都將返回這個(gè)唯一的bean實(shí)例。該作用域被稱為singleton,它是所有bean的默認(rèn)作用域。

當(dāng)bean的作用域?yàn)閱卫龝r(shí),Spring會在IOC容器對象創(chuàng)建時(shí)就創(chuàng)建bean的對象實(shí)例。而當(dāng)bean的作用域?yàn)閜rototype時(shí),IOC容器在獲取bean的實(shí)例時(shí)創(chuàng)建bean的實(shí)例對象。

2.8 ?bean的生命周期

  • Spring IOC容器可以管理bean的生命周期,Spring允許在bean生命周期內(nèi)特定的時(shí)間點(diǎn)執(zhí)行指定的任務(wù)。
  • Spring IOC容器對bean的生命周期進(jìn)行管理的過程:

① 通過構(gòu)造器或工廠方法創(chuàng)建bean實(shí)例

② 為bean的屬性設(shè)置值和對其他bean的引用

③ 調(diào)用bean的初始化方法

④ bean可以使用了

⑤?當(dāng)容器關(guān)閉時(shí),調(diào)用bean的銷毀方法

  • 在配置bean時(shí),通過init-method和destroy-method 屬性為bean指定初始化和銷毀方法
  • bean的后置處理器

① bean后置處理器允許在調(diào)用初始化方法前后對bean進(jìn)行額外的處理

② bean后置處理器對IOC容器里的所有bean實(shí)例逐一處理,而非單一實(shí)例。其典型 ???應(yīng)用是:檢查bean屬性的正確性或根據(jù)特定的標(biāo)準(zhǔn)更改bean的屬性。

③ bean后置處理器時(shí)需要實(shí)現(xiàn)接口:

org.springframework.beans.factory.config.BeanPostProcessor。在初始化方法被調(diào)用前

后,Spring將把每個(gè)bean實(shí)例分別傳遞給上述接口的以下兩個(gè)方法:

  • postProcessBeforeInitialization(Object, String)
  • postProcessAfterInitialization(Object, String)
  • 添加bean后置處理器后bean的生命周期

①通過構(gòu)造器或工廠方法創(chuàng)建bean實(shí)例

②為bean的屬性設(shè)置值和對其他bean的引用

③將bean實(shí)例傳遞給bean后置處理器的postProcessBeforeInitialization()方法

④調(diào)用bean的初始化方法

⑤將bean實(shí)例傳遞給bean后置處理器的postProcessAfterInitialization()方法

⑥bean可以使用了

⑦當(dāng)容器關(guān)閉時(shí)調(diào)用bean的銷毀方法

2.9 引用外部屬性文件

當(dāng)bean的配置信息逐漸增多時(shí),查找和修改一些bean的配置信息就變得愈加困難。這時(shí)可以將一部分信息提取到bean配置文件的外部,以properties格式的屬性文件保存起來,同時(shí)在bean的配置文件中引用properties屬性文件中的內(nèi)容,從而實(shí)現(xiàn)一部分屬性值在發(fā)生變化時(shí)僅修改properties屬性文件即可。這種技術(shù)多用于連接數(shù)據(jù)庫的基本信息的配置。

2.9.1 直接配置

<!-- 直接配置 -->

<bean?id="dataSource"?class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property?name="user"?value="root"/>

<property?name="password"?value="root"/>

<property?name="jdbcUrl"?value="jdbc:mysql:///test"/>

<property?name="driverClass"?value="com.mysql.jdbc.Driver"/>

</bean>

2.9.2 使用外部的屬性文件

1. 創(chuàng)建properties屬性文件

prop.userName=root

prop.password=root

prop.url=jdbc:mysql:///test

prop.driverClass=com.mysql.jdbc.Driver

2. 引入context名稱空間

3.指定properties屬性文件的位置

<!-- 指定properties屬性文件的位置 -->

<!-- classpath:xxx 表示屬性文件位于類路徑下 -->

<context:property-placeholder?location="classpath:jdbc.properties"/>

4.從properties屬性文件中引入屬性值

<!-- 從properties屬性文件中引入屬性值 -->

<bean?id="dataSource"?class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property?name="user"?value="${prop.userName}"/>

<property?name="password"?value="${prop.password}"/>

<property?name="jdbcUrl"?value="${prop.url}"/>

<property?name="driverClass"?value="${prop.driverClass}"/>

</bean>

2.10 自動(dòng)裝配

2.10.1 自動(dòng)裝配的概念

  • 手動(dòng)裝配:以value或ref的方式明確指定屬性值都是手動(dòng)裝配。
  • 自動(dòng)裝配:根據(jù)指定的裝配規(guī)則,不需要明確指定,Spring自動(dòng)將匹配的屬性值注入bean中。

 

2.10.2 裝配模式

  • 根據(jù)類型自動(dòng)裝配:將類型匹配的bean作為屬性注入到另一個(gè)bean中。若IOC容器中有多個(gè)與目標(biāo)bean類型一致的bean,Spring將無法判定哪個(gè)bean最合適該屬性,所以不能執(zhí)行自動(dòng)裝配
  • 根據(jù)名稱自動(dòng)裝配:必須將目標(biāo)bean的名稱和屬性名設(shè)置的完全相同
  • 通過構(gòu)造器自動(dòng)裝配:當(dāng)bean中存在多個(gè)構(gòu)造器時(shí),此種自動(dòng)裝配方式將會很復(fù)雜。不推薦使用。

    2.10.3 選用建議

    相對于使用注解的方式實(shí)現(xiàn)的自動(dòng)裝配,在XML文檔中進(jìn)行的自動(dòng)裝配略顯笨拙,在項(xiàng)目中更多的使用注解的方式實(shí)現(xiàn)。

2.11 SpEL

2.11.1 簡介

Spring Expression Language,Spring表達(dá)式語言,簡稱SpEL。支持運(yùn)行時(shí)查詢并可以操作對象圖。

和JSP頁面上的EL表達(dá)式、Struts2中用到的OGNL表達(dá)式一樣,SpEL根據(jù)JavaBean風(fēng)格的getXxx()、setXxx()方法定義的屬性訪問對象圖,完全符合我們熟悉的操作習(xí)慣。

2.11.2 基本語法

SpEL使用#{…}作為定界符,所有在大框號中的字符都將被認(rèn)為是SpEL表達(dá)式。

2.11.3 使用字面量

  • 整數(shù):<property name="count" value="#{5}"/>
  • 小數(shù):<property name="frequency" value="#{89.7}"/>
  • 科學(xué)計(jì)數(shù)法:<property name="capacity" value="#{1e4}"/>
  • String類型的字面量可以使用單引號或者雙引號作為字符串的定界符號

<property name="name" value="#{'Chuck'}"/>

<property name="name" value='#{"Chuck"}'/>

  • ?
  • Boolean:<property name="enabled" value="#{false}"/>

    2.11.4 引用其他bean

    <bean?id="emp04"?class="com.atguigu.parent.bean.Employee">

    <property?name="empId"?value="1003"/>

    <property?name="empName"?value="Kate"/>

    <property?name="age"?value="21"/>

    <property?name="detp"?value="#{dept}"/>

    </bean>

2.11.5 引用其他bean的屬性值作為自己某個(gè)屬性的值

<bean?id="emp05"?class="com.atguigu.parent.bean.Employee">

<property?name="empId"?value="1003"/>

<property?name="empName"?value="Kate"/>

<property?name="age"?value="21"/>

<property?name="deptName"?value="#{dept.deptName}"/>

</bean>

2.11.6 調(diào)用非靜態(tài)方法

<!-- 創(chuàng)建一個(gè)對象,在SpEL表達(dá)式中調(diào)用這個(gè)對象的方法 -->

<bean?id="salaryGenerator"?class="com.atguigu.spel.bean.SalaryGenerator"/>

 

<bean?id="employee"?class="com.atguigu.spel.bean.Employee">

<!-- 通過對象方法的返回值為屬性賦值 -->

<property?name="salayOfYear"?value="#{salaryGenerator.getSalaryOfYear(5000)}"/>

</bean>

2.11.7 調(diào)用靜態(tài)方法

<bean?id="employee"?class="com.atguigu.spel.bean.Employee">

<!-- 在SpEL表達(dá)式中調(diào)用類的靜態(tài)方法 -->

<property?name="circle"?value="#{T(java.lang.Math).PI*20}"/>

</bean>

2.11.8 運(yùn)算符

  • 算術(shù)運(yùn)算符:+、-、*、/、%、^
  • 字符串連接:+
  • 比較運(yùn)算符:<、>、==、<=、>=、lt、gt、eq、le、ge
  • 邏輯運(yùn)算符:and, or, not, |
  • 三目運(yùn)算符:判斷條件?判斷結(jié)果為true時(shí)的取值:判斷結(jié)果為false時(shí)的取值
  • 正則表達(dá)式:matches

 

2.12 通過注解配置bean

2.12.1 概述

相對于XML方式而言,通過注解的方式配置bean更加簡潔和優(yōu)雅,而且和MVC組件化開發(fā)的理念十分契合,是開發(fā)中常用的使用方式。

2.12.2 使用注解標(biāo)識組件

  • 普通組件:@Component

標(biāo)識一個(gè)受Spring IOC容器管理的組件

  • 持久化層組件:@Repository

標(biāo)識一個(gè)受Spring IOC容器管理的持久化層組件

  • 業(yè)務(wù)邏輯層組件:@Service

標(biāo)識一個(gè)受Spring IOC容器管理的業(yè)務(wù)邏輯層組件

  • 表述層控制器組件:@Controller

標(biāo)識一個(gè)受Spring IOC容器管理的表述層控制器組件

  • 組件命名規(guī)則

①默認(rèn)情況:使用組件的簡單類名首字母小寫后得到的字符串作為bean的id

②使用組件注解的value屬性指定bean的id

注意:事實(shí)上Spring并沒有能力識別一個(gè)組件到底是不是它所標(biāo)記的類型,即使將

@Respository注解用在一個(gè)表述層控制器組件上面也不會產(chǎn)生任何錯(cuò)誤,所以 @Respository、@Service、@Controller這幾個(gè)注解僅僅是為了讓開發(fā)人員自己明確 當(dāng)前的組件扮演的角色。

2.12.3 ?掃描組件

組件被上述注解標(biāo)識后還需要通過Spring進(jìn)行掃描才能夠偵測到。

  • 指定被掃描的package

<context:component-scan?base-package="com.atguigu.component"/>

  • 詳細(xì)說明

base-package屬性指定一個(gè)需要掃描的基類包,Spring容器將會掃描這個(gè)基類包及其子包中的所有類。

②當(dāng)需要掃描多個(gè)包時(shí)可以使用逗號分隔。

③如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性過濾特定的類,示例:

<context:component-scan?

base-package="com.atguigu.component"?

resource-pattern="autowire/*.class"/>

 

④包含與排除

  • <context:include-filter>子節(jié)點(diǎn)表示要包含的目標(biāo)類

注意:通常需要與use-default-filters屬性配合使用才能夠達(dá)到“僅包含某些 組件”這樣的效果。即:通過將use-default-filters屬性設(shè)置為false, 禁用默認(rèn)過濾器,然后掃描的就只是include-filter中的規(guī)則指定的 組件了。

  • <context:exclude-filter>子節(jié)點(diǎn)表示要排除在外的目標(biāo)類
  • component-scan下可以擁有若干個(gè)include-filter和exclude-filter子節(jié)點(diǎn)
  • 過濾表達(dá)式

類別

示例

說明

annotation

com.atguigu.XxxAnnotation

過濾所有標(biāo)注了XxxAnnotation的類。這個(gè)規(guī)則根據(jù)目標(biāo)組件是否標(biāo)注了指定類型的注解進(jìn)行過濾。

assignable

com.atguigu.BaseXxx

過濾所有BaseXxx類的子類。這個(gè)規(guī)則根據(jù)目標(biāo)組件是否是指定類型的子類的方式進(jìn)行過濾。

aspectj

com.atguigu.*Service+

所有類名是以Service結(jié)束的,或這樣的類的子類。這個(gè)規(guī)則根據(jù)AspectJ表達(dá)式進(jìn)行過濾。

regex

com\.atguigu\.anno\.*

所有com.atguigu.anno包下的類。這個(gè)規(guī)則根據(jù)正則表達(dá)式匹配到的類名進(jìn)行過濾。

custom

com.atguigu.XxxTypeFilter

使用XxxTypeFilter類通過編碼的方式自定義過濾規(guī)則。該類必須實(shí)現(xiàn)org.springframework.core.type.filter.TypeFilter接口

  • JAR包

必須在原有JAR包組合的基礎(chǔ)上再導(dǎo)入一個(gè):spring-aop-4.0.0.RELEASE.jar

2.12.4 組件裝配

  • 需求

Controller組件中往往需要用到Service組件的實(shí)例,Service組件中往往需要用到 Repository組件的實(shí)例。Spring可以通過注解的方式幫我們實(shí)現(xiàn)屬性的裝配。

  • 實(shí)現(xiàn)依據(jù)

在指定要掃描的包時(shí),<context:component-scan> 元素會自動(dòng)注冊一個(gè)bean的后置處 理器:AutowiredAnnotationBeanPostProcessor的實(shí)例。該后置處理器可以自動(dòng)裝配標(biāo)記 了@Autowired、@Resource或@Inject注解的屬性。

  • @Autowired注解

①根據(jù)類型實(shí)現(xiàn)自動(dòng)裝配。

②構(gòu)造器、普通字段(即使是非public)、一切具有參數(shù)的方法都可以應(yīng)用@Autowired ??注解

③默認(rèn)情況下,所有使用@Autowired注解的屬性都需要被設(shè)置。當(dāng)Spring找不到匹 ???配的bean裝配屬性時(shí),會拋出異常。

④若某一屬性允許不被設(shè)置,可以設(shè)置@Autowired注解的required屬性為 false

⑤默認(rèn)情況下,當(dāng)IOC容器里存在多個(gè)類型兼容的bean時(shí),Spring會嘗試匹配bean ??的id值是否與變量名相同,如果相同則進(jìn)行裝配。如果bean的id值不相同,通過類????????????? ??型的自動(dòng)裝配將無法工作。此時(shí)可以在@Qualifier注解里提供bean的名稱。Spring ??甚至允許在方法的形參上標(biāo)注@Qualifiter注解以指定注入bean的名稱。 ⑥@Autowired注解也可以應(yīng)用在數(shù)組類型的屬性上,此時(shí)Spring將會把所有匹配的bean進(jìn)行自動(dòng)裝配。

⑦@Autowired注解也可以應(yīng)用在集合屬性上,此時(shí)Spring讀取該集合的類型信息,然后自動(dòng)裝配所有與之兼容的bean。

⑧@Autowired注解用在java.util.Map上時(shí),若該Map的鍵值為String,那么 Spring將自動(dòng)裝配與值類型兼容的bean作為值,并以bean的id值作為鍵。

  • @Resource

@Resource注解要求提供一個(gè)bean名稱的屬性,若該屬性為空,則自動(dòng)采用標(biāo)注處的變量或方法名作為bean的名稱。

  • @Inject

@Inject和@Autowired注解一樣也是按類型注入匹配的bean,但沒有reqired屬性。