目錄
一、Spring簡介
二、Spring體系結構
三、Core contaainer(核心容器)
3.1 IoC 容器
3.1.1IoC容器概述
3.1.2 Spring IOC的兩個容器
3.1.3 BeanFactory
3.1.4 ApplicationContext
3.1.5 BeanFactory 和 ApplicationContext 的區別:
3.2 依賴注入(Dependency Injection,DI)
3.2.1 什么是DI依賴注入?
3.3 依賴注入的實作方式
3.3.1 set注入(主流)
3.3.2 構造器注入(了解)
3.3.3 集合型別資料注入
3.3.4 使用p命名空間簡化配置(了解)
3.3.5 SpEL (了解)
3.3.6 properties檔案
3.3.7 import(團隊開發)
四、Spring中的 Bean
4.1 bean的配置
4.2 bean的實體化
4.3 Bean的三種實體化方式
4.4 bean屬性scope(作用域)
4.4.1 singleton
4.4.2 prototype
4.5 Bean的生命周期
一、Spring簡介
Spring 使創建 Java 企業應用程式變得容易,它提供了在企業環境中使用 Java 語言所需的一切,并支持 Groovy 和 Kotlin 作為 JVM 上的替代語言,并且可以根據應用程式的需求靈活地創建多種體系結構,從 Spring Framework 5.0 開始,Spring 需要 JDK 8(Java SE 8),并且已經為 JDK 9 提供了現成的支持,如圖1-1

圖1-1 Spring發展史
Spring 支持廣泛的應用場景,在大型企業中,應用程式通常存在很長時間,并且必須在升級周期不受開發人員控制的 JDK 和應用程式服務器上運行,其他服務器則可以作為單個 jar 運行,并且服務器可以嵌入云環境中,還有一些可能是不需要服務器的獨立應用程式(例如批處理或集成作業負載),
Spring 是開源的,它擁有一個龐大而活躍的社區,可以根據各種實際用例提供持續的反饋,這幫助 Spring 在很長一段時間內成功地 Developing 了,
GitHub社區:https://github.com/spring-projects
Spring 中文 檔案:Spring Framework 中文檔案 - Spring 框架概述 | Docs4devSpring 是一個開放源代碼的設計層面框架,它解決的是業務邏輯層和其他各層的松耦合問題,因此它將面向介面的編程思想貫穿整個系統應用,Spring是于2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson創建,簡單來說,Spring是一個分層的JavaSE/EE full-stack(一站式) 輕量級開源框架,https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/overview.html#overview-spring
官網 : Spring | Home
官方下載地址 : JFrog
Spring優勢
| ------------------------ | -------- |
| 方便解耦,簡化開發 | |
| 方便集成各種優秀框架 | |
| 方便程式的測驗 | |
| AOP編程的支持 | |
| 宣告式事務的支持 | |
| 降低JavaEE API的使用難度 | |
| Java原始碼是經典學習范例 | |

圖 1-2 Spring的優勢作用
二、Spring體系結構

圖 2-1 Spring體系結構
三、Core contaainer(核心容器)
-
核心容器:核心容器提供 Spring 框架的基本功能,核心容器的主要組件是 BeanFactory,它是工廠模式的實作,BeanFactory 使用控制反轉(IOC) 模式將應用程式的配置和依賴性規范與實際的應用程式代碼分開,
-
Spring 背景關系:Spring 背景關系是一個組態檔,向 Spring 框架提供背景關系資訊,Spring 背景關系包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和調度功能,
-
Spring AOP:通過配置管理特性,Spring AOP 模塊直接將面向切面的編程功能 , 集成到了 Spring 框架中,所以,可以很容易地使 Spring 框架管理任何支持 AOP的物件,Spring AOP 模塊為基于 Spring 的應用程式中的物件提供了事務管理服務,通過使用 Spring AOP,不用依賴組件,就可以將宣告性事務管理集成到應用程式中,
-
Spring DAO:JDBC DAO 抽象層提供了有意義的例外層次結構,可用該結構來管理例外處理和不同資料庫供應商拋出的錯誤訊息,例外層次結構簡化了錯誤處理,并且極大地降低了需要撰寫的例外代碼數量(例如打開和關閉連接),Spring DAO 的面向 JDBC 的例外遵從通用的 DAO 例外層次結構,
-
Spring ORM:Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的物件關系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map,所有這些都遵從 Spring 的通用事務和 DAO 例外層次結構,
-
Spring Web 模塊:Web 背景關系模塊建立在應用程式背景關系模塊之上,為基于 Web 的應用程式提供了背景關系,所以,Spring 框架支持與 Jakarta Struts 的集成,Web 模塊還簡化了處理多部分請求以及將請求引數系結到域物件的作業,
-
Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程式的 MVC 實作,通過策略介面,MVC 框架變成為高度可配置的,MVC 容納了大量視圖技術,其中包括 JSP、Velocity、Tiles、iText 和 POI,
3.1 IoC 容器
3.1.1IoC容器概述
- IoC(Inversion Of Control)控制反轉,Spring反向控制應用程式所需要使用的外部資源
- Spring控制的資源全部放置在Spring容器中,該容器稱為IoC容器
IoC是Spring框架的核心內容,使用多種方式完美的實作了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置實作IoC,
Spring容器在初始化時先讀取組態檔,根據組態檔或元資料創建與組織物件存入容器中,程式使用時再從Ioc容器中取出需要的物件,
控制反轉IoC(Inversion of Control),是一種設計思想,DI(依賴注入)是實作IoC的一種方法,也有人認為DI只是IoC的另一種說法,沒有IoC的程式中 , 我們使用面向物件編程 , 物件的創建與物件間的依賴關系完全硬編碼在程式中,物件的創建由程式自己控制,控制反轉后將物件的創建轉移給第三方,個人認為所謂控制反轉就是:獲得依賴物件的方式反轉了,(狂神說java)

圖3-1 IOC容器
IoC是Spring框架的核心內容,使用多種方式完美的實作了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置實作IoC,
Spring容器在初始化時先讀取組態檔,根據組態檔或元資料創建與組織物件存入容器中,程式使用時再從Ioc容器中取出需要的物件,
ctrl+V了這么多廢話,終于可以說重點了!
3.1.2 Spring IOC的兩個容器
對于 IoC 來說,最重要的就是容器,容器管理著 Bean 的生命周期,控制著 Bean 的依賴注入,
那么, Spring 如何設計容器的呢?
Spring 作者 Rod Johnson 設計了兩個介面用以表示容器,
-
BeanFactory
-
ApplicationContext
BeanFactory E西好用!,是就是個 HashMap,Key 是 BeanName,Value 是 Bean 實體,
ApplicationContext 可以稱之為 “高級容器”,因為他比 BeanFactory 多了更多的功能,他繼承了多個介面,因此具備了更多的功能,例如資源的獲取,支持多種訊息(例如 JSP tag 的支持),對 BeanFactory 多了工具級別的支持等待,所以你看他的名字,已經不是 BeanFactory 之類的工廠了,而是 “應用背景關系”, 代表著整個大容器的所有功能,該介面定義了一個 refresh 方法,此方法是所有閱讀 Spring 原始碼的人的最熟悉的方法,用于重繪整個容器,即重新加載/重繪所有的 bean,

圖 3-2 ApplicationContext 的介面類
其實還有其他介面....
3.1.3 BeanFactory
BeanFactory 位于設計的最底層,它提供了 Spring IoC 最底層的設計,其方法如下:

圖3-3 BeanFactory的方法體
- getBean 對應了多個方法來獲取配置給 Spring IoC 容器的 Bean,
1.按照型別拿 bean:bean = (Bean) factory.getBean(Bean.class);
注意:要在 Spring 中只配置了一個這種型別的實體,不然報錯,(如果有多個那 Spring 就懵了,不知道該獲取哪一個)
2. 按照 bean 的名字拿 bean:bean = (Bean) factory.getBean("beanName");
注意:這種方法不太安全,IDE 不會檢查其安全性(關聯性)
3. 按照名字和型別拿 bean:(推薦)bean = (Bean) factory.getBean("beanName", Bean.class); - isSingleton 用于判斷是否單例,如果判斷為真,其意思是該 Bean 在容器中是作為一個唯一單例存在的,而【isPrototype】則相反,如果判斷為真,意思是當你從容器中獲取 Bean,容器就為你生成一個新的實體,
注意:在默認情況下,【isSingleton】為 ture,而【isPrototype】為 false - 關于 type 的匹配,這是一個按 Java 型別匹配的方式
- getAliases 方法是獲取別名的方法
3.1.4 ApplicationContext

創建一個Service介面

寫入方法
public class UserServiceImpl implements UserService {
public void save() {
System.out.println("user service running...");
}
}
配置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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 1.創建spring控制的資源-->
<bean id="userService" class="impl.service.impl.UserServiceImpl"/>
</beans>
Test
public static void main(String[] args) {
//2.加載組態檔
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//3.獲取資源
UserService userService = (UserService) ctx.getBean("userService");
userService.save();
}
ApplicationContext 常見實作類:
1.ClassPathXmlApplicationContext:
讀取classpath中的資源
ApplicationContext c = new ClassPathXmlApplicationContext("applicationContext.xml");
2:FileSystemXmlApplicationContext:-
讀取指定路徑的資源
ApplicationContext a = new FileSystemXmlApplicationContext("c:/applicationContext.xml");
3.XmlWebApplicationContext:
需要在Web的環境才可運行
XmlWebApplicationContext ac = new XmlWebApplicationContext(); // 這時并沒有初始化容器 ac.setServletContext(servletContext); // 需要指定ServletContext物件 ac.setConfigLocation("/WEB-INF/applicationContext.xml"); // 指定組態檔路徑,開頭的斜線表示Web應用的根目錄 ac.refresh(); // 初始化容器
3.1.5 BeanFactory 和 ApplicationContext 的區別:
- BeanFactory:是Spring中最底層的介面,只提供了最簡單的IoC功能,負責配置,創建和管理bean,
在應用中,一般不使用 BeanFactory,而推薦使用ApplicationContext(應用背景關系),原因如下, - ApplicationContext:
1.繼承了 BeanFactory,擁有了基本的 IoC 功能;
2.除此之外,ApplicationContext 還提供了以下功能:
① 支持國際化;
② 支持訊息機制;
③ 支持統一的資源加載;
④ 支持AOP功能;

3.2 依賴注入(Dependency Injection,DI)
3.2.1 什么是DI依賴注入?
spring動態的向某個物件提供它所需要的其他物件,這一點是通過DI(Dependency Injection,依賴注入)來實作的,比如物件A需要操作資料庫,以前我們總是要在A中自己撰寫代碼來獲得一個Connection物件,有了 spring我們就只需要告訴spring,A中需要一個Connection,至于這個Connection怎么構造,何時構造,A不需要知道,在系統運行時,spring會在適當的時候制造一個Connection,然后像打針一樣,注射到A當中,這樣就完成了對各個物件之間關系的控制,A需要依賴 Connection才能正常運行,而這個Connection是由spring注入到A中的,依賴注入的名字就這么來的,那么DI是如何實作的呢? Java 1.3之后一個重要特征是反射(reflection),它允許程式在運行的時候動態的生成物件、執行物件的方法、改變物件的屬性,spring就是通過反射來實作注入的,
簡單來說什么是依賴注入,就是給屬性賦值(包括基本資料型別和參考資料型別)
java面向物件的方式,需要呼叫另一個java物件,采用"new 被呼叫者"的方式創建物件,缺點是呼叫與被呼叫者的耦合增強,不利于后期維護,

使用Spring框架后,物件不在由呼叫者創建,而是由Spring容器創建,容器會負責控制程式間的關系,而不是由呼叫者直接控制,我們稱控制權轉移的這種情況為Spring控制反轉!

3.3 依賴注入的實作方式
3.3.1 set注入(主流)
- 名稱:property
- 型別:**標簽**
- 歸屬:bean標簽
- 作用:使用set方法的形式為bean提供資源
- 格式:
```java
<bean>
<property />
</bean>
```
- 基本屬性:
```xml
<property name="propertyName" value="propertyValue" ref="beanId"/>
```
? name:對應bean中的屬性名,要求該屬性必須提供可訪問的set方法(嚴格規范為此名稱是set方法對應名稱)
? value:設定非參考型別屬性對應的值,不能與ref同時使用
? ref:設定參考型別屬性對應bean的id ,不能與value同時使用
- 注意:一個bean可以有多個property標簽
3.3.2 構造器注入(了解)
- 名稱:constructor-arg
- 型別:**標簽**
- 歸屬:bean標簽
- 作用:使用構造方法的形式為bean提供資源,兼容早期遺留系統的升級作業
- 格式:
```xml
<bean>
<constructor-arg />
</bean>
```
- 基本屬性:
```xml
<constructor-arg name="argsName" value="argsValue />
```
? name:對應bean中的構造方法所攜帶的引數名
? value:設定非參考型別構造方法引數對應的值,不能與ref同時使用
其他屬性:
```xml
<constructor-arg index="arg-index" type="arg-type" ref="beanId"/>
```
? ref:設定參考型別構造方法引數對應bean的id ,不能與value同時使用
? type :設定構造方法引數的型別,用于按型別匹配引數或進行型別校驗
? index :設定構造方法引數的位置,用于按位置匹配引數,引數index值從0開始計數
- 注意:一個bean可以有多個constructor-arg標簽
3.3.3 集合型別資料注入
- 名稱:array,list,set,map,props
- 型別:**標簽**
- 歸屬:property標簽 或 constructor-arg標簽
- 作用:注入集合資料型別屬性
- 格式:
```xml
<property>
<list></list>
</property>
```
(1)集合型別資料注入——list
```xml
<property name="al">
<list>
<value>itheima</value>
<value>66666</value>
</list>
</property>
```
(2)集合型別資料注入——props
```xml
<property name="properties">
<props>
<prop key="name">zhangsan666</prop>
<prop key="value">666666</prop>
</props>
</property>
```
(3)集合型別資料注入——array (了解)
```xml
<property name="arr">
<array>
<value>123456</value>
<value>66666</value>
</array>
</property>
```
(4)集合型別資料注入——set(了解)
```xml
<property name="hs">
<set>
<value>Test</value>
<value>66666</value>
</set>
</property>
```
(5)集合型別資料注入——map(了解)
```xml
<property name="hm">
<map>
<entry key="name" value="Test66666"/>
<entry key="value" value="6666666666"/>
</map>
</property>
3.3.4 使用p命名空間簡化配置(了解)
- 名稱:p:propertyName,p:propertyName-ref
- 型別:**屬性**
- 歸屬:bean標簽
- 作用:為bean注入屬性值
- 格式:
```xml
<bean p:propertyName="propertyValue" p:propertyName-ref="beanId"/>
```
- 注意:使用p命令空間需要先開啟spring對p命令空間的的支持,在beans標簽中添加對應空間支持
```xml
<bean
id="userService"
class="com.itheima.service.impl.UserServiceImpl"
p:userDao-ref="userDao"
p:bookDao-ref="bookDao"
/>
```
3.3.5 SpEL (了解)
- Spring提供了對EL運算式的支持,統一屬性注入格式
- 型別:**屬性值**
- 歸屬:value屬性值
- 作用:為bean注入屬性值
- 格式:
```xml
<property value="EL"></bean>
```
- 注意:所有屬性值不區分是否參考型別,統一使用value賦值
- 所有格式統一使用 value=“********”
- 常量 #{10} #{3.14} #{2e5} #{‘itcast’}
- 參考bean #{beanId}
- 參考bean屬性 #{beanId.propertyName}
- 參考bean方法 beanId.methodName().method2()
- 參考靜態方法 T(java.lang.Math).PI
- 運算子支持 #{3 lt 4 == 4 ge 3}
- 正則運算式支持 #{user.name matches‘[a-z]{6,}’}
- 集合支持 #{likes[3]}
3.3.6 properties檔案
- Spring提供了讀取外部properties檔案的機制,使用讀取到的資料為bean的屬性賦值
- 操作步驟
1.準備外部properties檔案
2.開啟context命名空間支持
```xml
xmlns:context="http://www.springframework.org/schema/context"
```
? 3.加載指定的properties檔案
```xml
<context:property-placeholder location="classpath:filename.properties">
```
? 4.使用加載的資料
```xml
<property name="propertyName" value="${propertiesName}"/>
```
- 注意:如果需要加載所有的properties檔案,可以使用`*.properties`表示加載所有的properties檔案
- 注意:讀取資料使用**${propertiesName}**格式進行,其中**propertiesName**指properties檔案中的屬性名
3.3.7 import(團隊開發)
- 名稱:import
- 型別:**標簽**
- 歸屬:beans標簽
- 作用:在當前組態檔中匯入其他組態檔中的項
- 格式:
```xml
<beans>
<import />
</beans>
```
- 基本屬性:
```xml
<import resource=“config.xml"/>
```
? resource:加載的組態檔名
- Spring容器加載多個組態檔
```java
new ClassPathXmlApplicationContext("config1.xml","config2.xml");
```
- Spring容器中的bean定義沖突問題
- 同id的bean,后定義的覆寫先定義的
- 匯入組態檔可以理解為將匯入的組態檔復制粘貼到對應位置
- 匯入組態檔的順序與位置不同可能會導致最終程式運行結果不同
想要測驗詳情請參考:狂神說Spring03:依賴注入(DI)
四、Spring中的 Bean
4.1 bean的配置
Spring中,XML組態檔的根元素是<beans>,<beans>中包含了多個<bean>子元素,每一個<bean>中定義了一個Bean
| 屬性名稱 | 描述 |
|---|---|
| id | 是一個 Bean 的唯一識別符號,Spring 容器對 Bean 的配置和管理都通過該屬性完成 |
| name | Spring 容器同樣可以通過此屬性對容器中的 Bean 進行配置和管理,name 屬性中可以為 Bean 指定多個名稱,每個名稱之間用逗號或分號隔開 |
| class | 該屬性指定了 Bean 的具體實作類,它必須是一個完整的類名,使用類的全限定名 |
| scope | 用于設定 Bean 實體的作用域,其屬性值有 singleton(單例)、prototype(原型)、request、session 和 global Session,其默認值是 singleton |
| constructor-arg | <bean>元素的子元素,可以使用此元素傳入構造引數進行實體化,該元素的 index 屬性指定構造引數的序號(從 0 開始),type 屬性指定構造引數的型別 |
| property | <bean>元素的子元素,用于呼叫 Bean 實體中的 Set 方法完成屬性賦值,從而完成依賴注入,該元素的 name 屬性指定 Bean 實體中的相應屬性名 |
| ref | <property> 和 <constructor-arg> 等元素的子元索,該元素中的 bean 屬性用于指定對 Bean 工廠中某個 Bean 實體的參考 |
| value | <property> 和 <constractor-arg> 等元素的子元素,用于直接指定一個常量值 |
| list | 用于封裝 List 或陣列型別的依賴注入 |
| set | 用于封裝 Set 型別屬性的依賴注入 |
| map | 用于封裝 Map 型別屬性的依賴注入 |
| entry | <map> 元素的子元素,用于設定一個鍵值對,其 key 屬性指定字串型別的鍵值,ref 或 value 子元素指定其值 |
4.2 bean的實體化
- 名稱:bean
- 型別:**標簽**
- 歸屬:beans標簽
- 作用:定義spring中的資源,受此標簽定義的資源將受到spring控制
- 格式:
```xml
<beans>
<bean />
</beans>
```
- 基本屬性:
```xml
<bean id="beanId" name="beanName1,beanName2" class="ClassName"></bean>
```
? id:bean的名稱,通過id值獲取bean
? class:bean的型別
? name:bean的名稱,可以通過name值獲取bean,用于多人配合時給bean起別名
測驗一下
創建一個介面以及實作類:
public interface UserService {
public void save();
}
public class UserServiceImpl implements UserService {
public void save() {
System.out.println("Hello world");
}
}
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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 1.創建spring控制的資源-->
<bean id="userService" class="com.service.impl.UserServiceImpl"/>
</beans>
注意:在Bean中為指定id和name,spring會將class當id值
創建測驗類:
public static void main(String[] args) {
//2.加載組態檔
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//3.獲取資源
UserService userService = (UserService) ctx.getBean("userService");
userService.save();
}
輸出了Hello world
4.3 Bean的三種實體化方式
BeanFactory作用
-
配置、創建以及管理Bean物件
-
維持Bean物件之間的依賴關系
-
負責Bean物件的生命周期
上面我們通過小案例了解了bean的大致概念,下面我們來學習Bean的實體化方式
①構造器實體化
指Spring容器通過Bean對應類中的默認無參構造方法實體化,
②靜態工廠實體化
創建靜態工廠的方法來創建Bean實體,其中Bean的class屬性所指定的不是Bean實作類而是靜態工廠類,需要使用factory-merhod屬性來指定創建的靜態工廠,
檔案 MyBean2Facory
public class MyBean2Facory {
//使用自己創建的Bean2工廠
public static Bean2 createBean(){
return new Bean2();
}
}
applicationContest.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="Bean2" class="instance.MyBean2Facory"
factory-method="createBean"/>
</beans>
③實體工廠實體化
創建實體工廠MyBean3Factory
public class MyBean3Facory {
public MyBean3Facory() {
System.out.println("bean3工廠實體化中....");
}
//使用自己創建的Bean2工廠
public Bean3 createBean(){
return new Bean3();
}
}
創建beans3.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="MyBean3Facory" class="instance.MyBean3Facory"/>
<!--使用factory-bean屬性執行實體工廠-->
<!--使用factory-method屬性確定使用的方法-->
<bean id="bean3" factory-bean="MyBean3Facory" factory-method="createBean"/>
</beans>
<!--使用factory-bean屬性執行實體工廠-->
<!--使用factory-method屬性確定使用的方法-->
測驗輸出

4.4 bean屬性scope(作用域)
作用域的型別;
| 作用域名稱 | 說明 |
| singleton | 默認值,單例模式,表示在 Spring 容器中只有一個 Bean 實體,Bean 以單例的方式存在, |
| prototype | 原型模式,表示每次通過 Spring 容器獲取 Bean 時,容器都會創建一個 Bean 實體, |
| request | 每次 HTTP 請求,容器都會創建一個 Bean 實體,該作用域只在當前 HTTP Request 內有效, |
| session | 同一個 HTTP Session 共享一個 Bean 實體,不同的 Session 使用不同的 Bean 實體,該作用域僅在當前 HTTP Session 內有效, |
| application | 同一個 Web 應用共享一個 Bean 實體,該作用域在當前 ServletContext 內有效,類似于 singleton,不同的是,singleton 表示每個 IoC 容器中僅有一個 Bean 實體,而同一個 Web 應用中可能會有多個 IoC 容器,但一個 Web 應用只會有一個 ServletContext,也可以說 application 才是 Web 應用中貨真價實的單例模式, |
| websocket | websocket 的作用域是 WebSocket ,即在整個 WebSocket 中有效, |
4.4.1 singleton
名稱:scope
- 型別:**作用域**
- 歸屬:bean標簽
- 作用:定義bean的作用范圍
- 格式:
- <bean id="..." class="..." scope="singleton"/>
HelloWorld 類代碼如下,
public class HelloWorld {
private String message;
public void setMessage(String message) {
this.message = message;
}
public void getMessage() {
System.out.println("message : " + message);
}
}
MainApp 類如下,
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
objA.setMessage("物件A");
objA.getMessage();
HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
objB.getMessage();
}
}
Beans.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-3.0.xsd">
<bean id="helloWorld" class="HelloWorld" scope="singleton"/>
</beans>
運行結果如下,
message : 物件A
message : 物件A
從運行結果可以看出,兩次輸出內容相同,這說明 Spring 容器只創建了一個 HelloWorld 類的實體,由于 Spring 容器默認作用域是 singleton,所以如果省略 scope 屬性,其輸出結果也會是一個實體,
4.4.2 prototype
名稱:scope
- 型別:**作用域**
- 歸屬:bean標簽
- 作用:定義bean的作用范圍
- 格式:
- <bean id="..." class="..." scope="prototype"/>
在上面例子 的基礎上,修改組態檔 Beans.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-3.0.xsd">
<bean id="helloWorld" class="HelloWorld" scope="prototype"/>
</beans>
運行結果如下,
message : 物件A
message : null
4.5 Bean的生命周期
Spring 根據 Bean 的作用域來選擇管理方式,對于 singleton 作用域的 Bean,Spring 能夠精確地知道該 Bean 何時被創建,何時初始化完成,以及何時被銷毀;而對于 prototype 作用域的 Bean,Spring 只負責創建,當容器創建了 Bean 的實體后,Bean 的實體就交給客戶端代碼管理,Spring 容器將不再跟蹤其生命周期,

了解 Spring 生命周期的意義就在于,可以利用 Bean 在其存活期間的指定時刻完成一些相關操作,一般情況下,會在 Bean 被初始化后和被銷毀前執行一些相關操作,
Spring 官方提供了 3 種方法實作初始化回呼和銷毀回呼:
- 實作 InitializingBean 和 DisposableBean 介面;
- 在 XML 中配置 init-method 和 destory-method;
- 使用 @PostConstruct 和 @PreDestory 注解,
在一個 Bean 中有多種生命周期回呼方法時,優先級為:注解 > 介面 > XML,
不建議使用介面和注解,這會讓 pojo 類和 Spring 框架緊耦合,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/395603.html
標籤:java
