日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring(3)——装配 Spring Bean 详解

發布時間:2025/3/21 javascript 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring(3)——装配 Spring Bean 详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

裝配 Bean 的概述

前面已經介紹了 Spring IoC 的理念和設計,這一篇文章將介紹的是如何將自己開發的 Bean 裝配到 Spring IoC 容器中。

大部分場景下,我們都會使用 ApplicationContext 的具體實現類,因為對應的 Spring IoC 容器功能相對強大。

而在 Spring 中提供了 3 種方法進行配置:

  • 在 XML 文件中顯式配置
  • 在 Java 的接口和類中實現配置
  • 隱式 Bean 的發現機制和自動裝配原則

方式選擇的原則

在現實的工作中,這 3 種方式都會被用到,并且在學習和工作之中常?;旌鲜褂?#xff0c;所以這里給出一些關于這 3 種優先級的建議:

1.最優先:通過隱式 Bean 的發現機制和自動裝配的原則。
基于約定由于配置的原則,這種方式應該是最優先的

  • 好處:減少程序開發者的決定權,簡單又不失靈活。

2.其次:Java 接口和類中配置實現配置
在沒有辦法使用自動裝配原則的情況下應該優先考慮此類方法

  • 好處:避免 XML 配置的泛濫,也更為容易。
  • 典型場景:一個父類有多個子類,比如學生類有兩個子類,一個男學生類和女學生類,通過 IoC 容器初始化一個學生類,容器將無法知道使用哪個子類去初始化,這個時候可以使用 Java 的注解配置去指定。

3.最后:XML 方式配置
在上述方法都無法使用的情況下,那么也只能選擇 XML 配置的方式。

  • 好處:簡單易懂(當然,特別是對于初學者)
  • 典型場景:當使用第三方類的時候,有些類并不是我們開發的,我們無法修改里面的代碼,這個時候就通過 XML 的方式配置使用了。

通過 XML 配置裝配 Bean

使用 XML 裝配 Bean 需要定義對應的 XML,這里需要引入對應的 XML 模式(XSD)文件,這些文件會定義配置 Spring Bean 的一些元素,當我們在 IDEA 中創建 XML 文件時,會有友好的提示:

一個簡單的 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"></beans>

這就只是一個格式文件,引入了一個 beans 的定義,引入了 xsd 文件,它是一個根元素,這樣它所定義的元素將可以定義對應的 Spring Bean

裝配簡易值

先來一個最簡單的裝配:

<bean id="c" class="pojo.Category"><property name="name" value="測試" /> </bean>

簡單解釋一下:

  • id?屬性是 Spring 能找到當前 Bean 的一個依賴的編號,遵守 XML 語法的 ID 唯一性約束。必須以字母開頭,可以使用字母、數字、連字符、下劃線、句號、冒號,不能以?/?開頭
    不過?id?屬性不是一個必需的屬性,name?屬性也可以定義 bean 元素的名稱,能以逗號或空格隔開起多個別名,并且可以使用很多的特殊字符,比如在 Spring 和 Spring MVC 的整合中,就得使用?name?屬性來定義 bean 的名稱,并且使用?/?開頭。
    注意:?從 Spring 3.1 開始,id?屬性也可以是 String 類型了,也就是說?id?屬性也可以使用?/?開頭,而 bean 元素的 id 的唯一性由容器負責檢查。
    如果?id?和?name?屬性都沒有聲明的話,那么 Spring 將會采用?“全限定名#{number}”?的格式生成編號。 例如這里,如果沒有聲明 “id="c"” 的話,那么 Spring 為其生成的編號就是 “pojo.Category#0”,當它第二次聲明沒有?id?屬性的 Bean 時,編號就是 “pojo.Category#1”,以此類推。
  • class?屬性顯然就是一個類的全限定名
  • property?元素是定義類的屬性,其中的?name?屬性定義的是屬性的名稱,而?value?是它的值。

這樣的定義很簡單,但是有時候需要注入一些自定義的類,比如之前飲品店的例子,JuickMaker 需要用戶提供原料信息才能完成 juice 的制作:

<!-- 配置 srouce 原料 --> <bean name="source" class="pojo.Source"><property name="fruit" value="橙子"/><property name="sugar" value="多糖"/><property name="size" value="超大杯"/> </bean><bean name="juickMaker" class="pojo.JuiceMaker"><!-- 注入上面配置的id為srouce的Srouce對象 --><property name="source" ref="source"/> </bean>

這里先定義了一個?name?為 source 的 Bean,然后再制造器中通過?ref?屬性去引用對應的 Bean,而 source 正是之前定義的 Bean 的?name?,這樣就可以相互引用了。

  • 注入對象:使用?ref?屬性

裝配集合

有些時候我們需要裝配一些復雜的東西,比如 Set、Map、List、Array 和 Properties 等,為此我們在 Packge【pojo】下新建一個 ComplexAssembly 類:

package pojo;import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set;public class ComplexAssembly {private Long id;private List<String> list;private Map<String, String> map;private Properties properties;private Set<String> set;private String[] array;/* setter and getter */ }

這個 Bean 沒有任何的實際意義,知識為了介紹如何裝配這些常用的集合類:

<bean id="complexAssembly" class="pojo.ComplexAssembly"><!-- 裝配Long類型的id --><property name="id" value="1"/><!-- 裝配List類型的list --><property name="list"><list><value>value-list-1</value><value>value-list-2</value><value>value-list-3</value></list></property><!-- 裝配Map類型的map --><property name="map"><map><entry key="key1" value="value-key-1"/><entry key="key2" value="value-key-2"/><entry key="key3" value="value-key-2"/></map></property><!-- 裝配Properties類型的properties --><property name="properties"><props><prop key="prop1">value-prop-1</prop><prop key="prop2">value-prop-2</prop><prop key="prop3">value-prop-3</prop></props></property><!-- 裝配Set類型的set --><property name="set"><set><value>value-set-1</value><value>value-set-2</value><value>value-set-3</value></set></property><!-- 裝配String[]類型的array --><property name="array"><array><value>value-array-1</value><value>value-array-2</value><value>value-array-3</value></array></property> </bean>
  • 總結:
  • List 屬性為對應的?<list>?元素進行裝配,然后通過多個?<value>?元素設值
  • Map 屬性為對應的?<map>?元素進行裝配,然后通過多個?<entry>?元素設值,只是?entry?包含一個鍵值對(key-value)的設置
  • Properties 屬性為對應的?<properties>?元素進行裝配,通過多個?<property>?元素設值,只是?properties?元素有一個必填屬性?key?,然后可以設置值
  • Set 屬性為對應的?<set>?元素進行裝配,然后通過多個?<value>?元素設值
  • 對于數組而言,可以使用?<array>?設置值,然后通過多個?<value>?元素設值。

上面看到了對簡單 String 類型的各個集合的裝載,但是有些時候可能需要更為復雜的裝載,比如一個 List 可以是一個系列類的對象,為此需要定義注入的相關信息,其實跟上面的配置沒什么兩樣,只不過加入了?ref?這一個屬性而已:

  • 集合注入總結:
  • List 屬性使用?<list>?元素定義注入,使用多個?<ref>?元素的 Bean 屬性去引用之前定義好的 Bean
<property name="list"><list><ref bean="bean1"/><ref bean="bean2"/></list> </property>
  • Map 屬性使用?<map>?元素定義注入,使用多個?<entry>?元素的?key-ref?屬性去引用之前定義好的 Bean 作為鍵,而用?value-ref?屬性引用之前定義好的 Bean 作為值
<property name="map"><map><entry key-ref="keyBean" value-ref="valueBean"/></map> </property>
  • Set 屬性使用?<set>?元素定義注入,使用多個?<ref>?元素的?bean?去引用之前定義好的 Bean
<property name="set"><set><ref bean="bean"/></set> </property>

命名空間裝配

除了上述的配置之外, Spring 還提供了對應的命名空間的定義,只是在使用命名空間的時候要先引入對應的命名空間和 XML 模式(XSD)文件。

——【① c-命名空間】——

c-命名空間是在 Spring 3.0 中引入的,它是在 XML 中更為簡潔地描述構造器參數的方式,要使用它的話,必須要在 XML 的頂部聲明其模式:

  • 注意:是通過構造器參數的方式

現在假設我們現在有這么一個類:

package pojo;public class Student {int id;String name;public Student(int id, String name) {this.id = id;this.name = name;}// setter and getter }

在 c-命名空間和模式聲明之后,我們就可以使用它來聲明構造器參數了:

<!-- 引入 c-命名空間之前 --> <bean name="student1" class="pojo.Student"><constructor-arg name="id" value="1" /><constructor-arg name="name" value="學生1"/> </bean><!-- 引入 c-命名空間之后 --> <bean name="student2" class="pojo.Student"c:id="2" c:name="學生2"/>

c-命名空間屬性名以 “c:” 開頭,也就是命名空間的前綴。接下來就是要裝配的構造器參數名,在此之后如果需要注入對象的話則要跟上?-ref(如c:card-ref="idCard1",則對 card 這個構造器參數注入之前配置的名為 idCard1 的 bean)

很顯然,使用 c-命名空間屬性要比使用?<constructor-arg>?元素精簡,并且會直接引用構造器之中參數的名稱,這有利于我們使用的安全性。

我們有另外一種替代方式:

<bean name="student2" class="pojo.Student"c:_0="3" c:_1="學生3"/>

我們將參數的名稱替換成了 “0” 和 “1” ,也就是參數的索引。因為在 XML 中不允許數字作為屬性的第一個字符,因此必須要添加一個下劃線來作為前綴。

——【② p-命名空間】——

c-命名空間通過構造器注入的方式來配置 bean,p-命名空間則是用setter的注入方式來配置 bean ,同樣的,我們需要引入聲明:

然后我們就可以通過 p-命名空間來設置屬性:

<!-- 引入p-命名空間之前 --> <bean name="student1" class="pojo.Student"><property name="id" value="1" /><property name="name" value="學生1"/> </bean><!-- 引入p-命名空間之后 --> <bean name="student2" class="pojo.Student" p:id="2" p:name="學生2"/>

我們需要先刪掉 Student 類中的構造函數,不然 XML 約束會提示我們配置?<constructor-arg>?元素。

同樣的,如果屬性需要注入其他 Bean 的話也可以在后面跟上?-ref:

<bean name="student2" class="pojo.Student"p:id="2" p:name="學生2" p:cdCard-ref="cdCard1"/>

——【③ util-命名空間】——

工具類的命名空間,可以簡化集合類元素的配置,同樣的我們需要引入其聲明(無需擔心怎么聲明的問題,IDEA會有很友好的提示):

我們來看看引入前后的變化:

<!-- 引入util-命名空間之前 --> <property name="list"><list><ref bean="bean1"/><ref bean="bean2"/></list> </property><!-- 引入util-命名空間之后 --> <util:list id="list"><ref bean="bean1"/><ref bean="bean2"/> </util:list>

<util:list>?只是 util-命名空間中的多個元素之一,下表提供了 util-命名空間提供的所有元素:

元素描述
<util:constant>引用某個類型的?public static?域,并將其暴露為 bean
<util:list>創建一個?java.util.List?類型的 bean,其中包含值或引用
<util:map>創建一個?java.util.map?類型的 bean,其中包含值或引用
<util:properties>創建一個?java.util.Properties?類型的 bean
<util:property-path>引用一個 bean 的屬性(或內嵌屬性),并將其暴露為 bean
<util:set>創建一個?java.util.Set?類型的 bean,其中包含值或引用

引入其他配置文件

在實際開發中,隨著應用程序規模的增加,系統中?<bean>?元素配置的數量也會大大增加,導致 applicationContext.xml 配置文件變得非常臃腫難以維護。

  • 解決方案:讓 applicationContext.xml 文件包含其他配置文件即可
    使用?<import>?元素引入其他配置文件

1.在【src】文件下新建一個 bean.xml 文件,寫好基礎的約束,把 applicationContext.xml 文件中配置的?<bean>?元素復制進去

2.在 applicationContext.xml 文件中寫入:

<import resource="bean.xml" />

3.運行測試代碼,仍然能正確獲取到 bean:


通過注解裝配 Bean

上面,我們已經了解了如何使用 XML 的方式去裝配 Bean,但是更多的時候已經不再推薦使用 XML 的方式去裝配 Bean,更多的時候回考慮使用注解(annotation) 的方式去裝配 Bean。

  • 優勢:
    1.可以減少 XML 的配置,當配置項多的時候,臃腫難以維護
    2.功能更加強大,既能實現 XML 的功能,也提供了自動裝配的功能,采用了自動裝配后,程序猿所需要做的決斷就少了,更加有利于對程序的開發,這就是“約定由于配置”的開發原則

在 Spring 中,它提供了兩種方式來讓 Spring IoC 容器發現 bean:

  • 組件掃描:通過定義資源的方式,讓 Spring IoC 容器掃描對應的包,從而把 bean 裝配進來。
  • 自動裝配:通過注解定義,使得一些依賴關系可以通過注解完成。

使用@Compoent 裝配 Bean

我們把之前創建的 Student 類改一下:

package pojo;import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;@Component(value = "student1") public class Student {@Value("1")int id;@Value("student_name_1")String name;// getter and setter }

解釋一下:

  • @Component注解:
    表示 Spring IoC 會把這個類掃描成一個 bean 實例,而其中的?value?屬性代表這個類在 Spring 中的?id,這就相當于在 XML 中定義的 Bean 的 id:<bean id="student1" class="pojo.Student" />,也可以簡寫成?@Component("student1"),甚至直接寫成?@Component?,對于不寫的,Spring IoC 容器就默認以類名來命名作為?id,只不過首字母小寫,配置到容器中。
  • @Value注解:
    表示值的注入,跟在 XML 中寫?value?屬性是一樣的。

這樣我們就聲明好了我們要創建的一個 Bean,就像在 XML 中寫下了這樣一句話:

<bean name="student1" class="pojo.Student"><property name="id" value="1" /><property name="name" value="student_name_1"/> </bean>

但是現在我們聲明了這個類,并不能進行任何的測試,因為 Spring IoC 并不知道這個 Bean 的存在,這個時候我們可以使用一個 StudentConfig 類去告訴 Spring IoC :

package pojo; import org.springframework.context.annotation.ComponentScan;@ComponentScan public class StudentConfig { }

這個類十分簡單,沒有任何邏輯,但是需要說明兩點:

  • 該類和 Student 類位于同一包名下
  • @ComponentScan注解:
    代表進行掃描,默認是掃描當前包的路徑,掃描所有帶有?@Component?注解的 POJO。

這樣一來,我們就可以通過 Spring 定義好的 Spring IoC 容器的實現類——AnnotationConfigApplicationContext 去生成 IoC 容器了:

ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class); Student student = (Student) context.getBean("student1", Student.class); student.printInformation();

這里可以看到使用了 AnnotationConfigApplicationContext 類去初始化 Spring IoC 容器,它的配置項是 StudentConfig 類,這樣 Spring IoC 就會根據注解的配置去解析對應的資源,來生成 IoC 容器了。

  • 明顯的弊端:
  • 對于?@ComponentScan?注解,它只是掃描所在包的 Java 類,但是更多的時候我們希望的是可以掃描我們指定的類
  • 上面的例子只是注入了一些簡單的值,測試發現,通過?@Value?注解并不能注入對象

@Component?注解存在著兩個配置項:

  • basePackages:它是由 base 和 package 兩個單詞組成的,而 package 還是用了復數,意味著它可以配置一個 Java 包的數組,Spring 會根據它的配置掃描對應的包和子包,將配置好的 Bean 裝配進來
  • basePackageClasses:它由 base、package 和 class 三個單詞組成,采用復數,意味著它可以配置多個類, Spring 會根據配置的類所在的包,為包和子包進行掃描裝配對應配置的 Bean

我們來試著重構之前寫的 StudentConfig 類來驗證上面兩個配置項:

package pojo; import org.springframework.context.annotation.ComponentScan;@ComponentScan(basePackages = "pojo") public class StudentConfig { }// —————————————————— 【 宇宙超級無敵分割線】—————————————————— package pojo;import org.springframework.context.annotation.ComponentScan;@ComponentScan(basePackageClasses = pojo.Student.class) public class StudentConfig { }

驗證都能通過,bingo!

  • 對于 【basePackages】 和 【basePackageClasses】 的選擇問題:
    【basePackages】 的可讀性會更好一些,所以在項目中會優先選擇使用它,但是在需要大量重構的工程中,盡量不要使用【basePackages】,因為很多時候重構修改包名需要反復地配置,而 IDE 不會給你任何的提示,而采用【basePackageClasses】會有錯誤提示。

自動裝配——@Autowired

上面提到的兩個弊端之一就是沒有辦法注入對象,通過自動裝配我們將解決這個問題。

所謂自動裝配技術是一種由 Spring 自己發現對應的 Bean,自動完成裝配工作的方式,它會應用到一個十分常用的注解?@Autowired?上,這個時候?Spring 會根據類型去尋找定義的 Bean 然后將其注入,聽起來很神奇,讓我們實際來看一看:

1.先在 Package【service】下創建一個 StudentService 接口:

package service;public interface StudentService {public void printStudentInfo(); }

使用接口是 Spring 推薦的方式,這樣可以更為靈活,可以將定義和實現分離

2.為上面的接口創建一個 StudentServiceImp 實現類:

package service;import org.springframework.beans.factory.annotation.Autowired; import pojo.Student;@Component("studentService") public class StudentServiceImp implements StudentService {@Autowiredprivate Student student = null;// getter and setterpublic void printStudentInfo() {System.out.println("學生的 id 為:" + student.getName());System.out.println("學生的 name 為:" + student.getName());} }

該實現類實現了接口的 printStudentInfo() 方法,打印出成員對象 student 的相關信息,這里的?@Autowired?注解,表示在 Spring IoC 定位所有的 Bean 后,這個字段需要按類型注入,這樣 IoC 容器就會尋找資源,然后將其注入。

3.編寫測試類:

// 第一步:修改 StudentConfig 類,告訴 Spring IoC 在哪里去掃描它: package pojo;import org.springframework.context.annotation.ComponentScan;@ComponentScan(basePackages = {"pojo", "service"}) public class StudentConfig { }// 或者也可以在 XML 文件中聲明去哪里做掃描 <context:component-scan base-package="pojo" /> <context:component-scan base-package="service" />// 第二步:編寫測試類: package test;import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import pojo.StudentConfig; import service.StudentService; import service.StudentServiceImp;public class TestSpring {public static void main(String[] args) {// 通過注解的方式初始化 Spring IoC 容器ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);StudentService studentService = context.getBean("studentService", StudentServiceImp.class);studentService.printStudentInfo();} }

運行代碼:

  • 再次理解:?@Autowired?注解表示在 Spring IoC 定位所有的 Bean 后,再根據類型尋找資源,然后將其注入。
  • 過程:?定義 Bean ——》 初始化 Bean(掃描) ——》 根據屬性需要從 Spring IoC 容器中搜尋滿足要求的 Bean ——》 滿足要求則注入
  • 問題:?IoC 容器可能會尋找失敗,此時會拋出異常(默認情況下,Spring IoC 容器會認為一定要找到對應的 Bean 來注入到這個字段,但有些時候并不是一定需要,比如日志)
  • 解決:?通過配置項?required?來改變,比如?@Autowired(required = false)

@Autowired?注解不僅僅能配置在屬性之上,還允許方法配置,常見的 Bean 的 setter 方法也可以使用它來完成注入,總之一切需要 Spring IoC 去尋找 Bean 資源的地方都可以用到,例如:

/* 包名和import */ public class JuiceMaker {......@Autowiredpublic void setSource(Source source) {this.source = source;} }

在大部分的配置中都推薦使用這樣的自動注入來完成,這是 Spring IoC 幫助我們自動裝配完成的,這樣使得配置大幅度減少,滿足約定優于配置的原則,增強程序的健壯性。

自動裝配的歧義性(@Primary和@Qualifier)

在上面的例子中我們使用?@Autowired?注解來自動注入一個 Source 類型的 Bean 資源,但如果我們現在有兩個 Srouce 類型的資源,Spring IoC 就會不知所措,不知道究竟該引入哪一個 Bean:

<bean name="source1" class="pojo.Source"><property name="fruit" value="橙子"/><property name="sugar" value="多糖"/><property name="size" value="超大杯"/> </bean> <bean name="source2" class="pojo.Source"><property name="fruit" value="橙子"/><property name="sugar" value="少糖"/><property name="size" value="小杯"/> </bean>

我們可以會想到 Spring IoC 最底層的容器接口——BeanFactory 的定義,它存在一個按照類型獲取 Bean 的方法,顯然通過 Source.class 作為參數無法判斷使用哪個類實例進行返回,這就是自動裝配的歧義性。

為了消除歧義性,Spring 提供了兩個注解:

  • @Primary 注解:
    代表首要的,當 Spring IoC 檢測到有多個相同類型的 Bean 資源的時候,會優先注入使用該注解的類。
  • 問題:該注解只是解決了首要的問題,但是并沒有選擇性的問題
  • @Qualifier 注解:
    上面所談及的歧義性,一個重要的原因是 Spring 在尋找依賴注入的時候是按照類型注入引起的。除了按類型查找 Bean,Spring IoC 容器最底層的接口 BeanFactory 還提供了按名字查找的方法,如果按照名字來查找和注入不就能消除歧義性了嗎?
  • 使用方法:?指定注入名稱為 "source1" 的 Bean 資源
/* 包名和import */ public class JuiceMaker {......@Autowired@Qualifier("source1")public void setSource(Source source) {this.source = source;} }

使用@Bean 裝配 Bean

  • 問題:?以上都是通過?@Component?注解來裝配 Bean ,并且只能注解在類上,當你需要引用第三方包的(jar 文件),而且往往并沒有這些包的源碼,這時候將無法為這些包的類加入?@Component?注解,讓它們變成開發環境中的 Bean 資源。
  • 解決方案:
    1.自己創建一個新的類來擴展包里的類,然后再新類上使用?@Component?注解,但這樣很 low
    2.使用?@Bean?注解,注解到方法之上,使其成為 Spring 中返回對象為 Spring 的 Bean 資源。

我們在 Package【pojo】 下新建一個用來測試?@Bean?注解的類:

package pojo;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration public class BeanTester {@Bean(name = "testBean")public String test() {String str = "測試@Bean注解";return str;} }
  • 注意:?@Configuration?注解相當于 XML 文件的根元素,必須要,有了才能解析其中的?@Bean?注解

然后我們在測試類中編寫代碼,從 Spring IoC 容器中獲取到這個 Bean :

// 在 pojo 包下掃描 ApplicationContext context = new AnnotationConfigApplicationContext("pojo"); // 因為這里獲取到的 Bean 就是 String 類型所以直接輸出 System.out.println(context.getBean("testBean"));

@Bean?的配置項中包含 4 個配置項:

  • name:?是一個字符串數組,允許配置多個 BeanName
  • autowire:?標志是否是一個引用的 Bean 對象,默認值是 Autowire.NO
  • initMethod:?自定義初始化方法
  • destroyMethod:?自定義銷毀方法

使用?@Bean?注解的好處就是能夠動態獲取一個 Bean 對象,能夠根據環境不同得到不同的 Bean 對象。或者說將 Spring 和其他組件分離(其他組件不依賴 Spring,但是又想 Spring 管理生成的 Bean)

Bean 的作用域

在默認的情況下,Spring IoC 容器只會對一個 Bean 創建一個實例,但有時候,我們希望能夠通過 Spring IoC 容器獲取多個實例,我們可以通過?@Scope?注解或者?<bean>?元素中的?scope?屬性來設置,例如:

// XML 中設置作用域 <bean id="" class="" scope="prototype" /> // 使用注解設置作用域 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

Spring 提供了 5 種作用域,它會根據情況來決定是否生成新的對象:

作用域類別描述
singleton(單例)在Spring IoC容器中僅存在一個Bean實例 (默認的scope)
prototype(多例)每次從容器中調用Bean時,都返回一個新的實例,即每次調用getBean()時 ,相當于執行new XxxBean():不會在容器啟動時創建對象
request(請求)用于web開發,將Bean放入request范圍 ,request.setAttribute("xxx") , 在同一個request 獲得同一個Bean
session(會話)用于web開發,將Bean 放入Session范圍,在同一個Session 獲得同一個Bean
globalSession(全局會話)一般用于 Porlet 應用環境 , 分布式系統存在全局 session 概念(單點登錄),如果不是 porlet 環境,globalSession 等同于 Session

在開發中主要使用?scope="singleton"、scope="prototype",對于MVC中的Action使用prototype類型,其他使用singleton,Spring容器會管理 Action 對象的創建,此時把 Action 的作用域設置為 prototype.

擴展閱讀:@Profile 注解?、?條件化裝配 Bean

Spring 表達式語言簡要說明

Spring 還提供了更靈活的注入方式,那就是 Spring 表達式,實際上 Spring EL 遠比以上注入方式都要強大,它擁有很多功能:

  • 使用 Bean 的 id 來引用 Bean
  • 調用指定對象的方法和訪問對象的屬性
  • 進行運算
  • 提供正則表達式進行匹配
  • 集合配置

我們來看一個簡單的使用 Spring 表達式的例子:

package pojo;import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;@Component("elBean") public class ElBean {// 通過 beanName 獲取 bean,然后注入 @Value("#{role}")private Role role;// 獲取 bean 的屬性 id@Value("#{role.id}")private Long id;// 調用 bean 的 getNote 方法@Value("#{role.getNote().toString()}")private String note;/* getter and setter */ }

與屬性文件中讀取使用的 “$” 不同,在 Spring EL 中則使用 “#”

擴展閱讀:?Spring 表達式語言

參考資料:

  • 《Java EE 互聯網輕量級框架整合開發》
  • 《Java 實戰(第四版)》
  • 萬能的百度 and 萬能的大腦

歡迎轉載,轉載請注明出處!
簡書ID:@我沒有三顆心臟

總結

以上是生活随笔為你收集整理的Spring(3)——装配 Spring Bean 详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。