主頁 > 後端開發 > Enterprise-level Spring-探索Spring-從入門到入廠

Enterprise-level Spring-探索Spring-從入門到入廠

2021-12-28 18:41:01 後端開發

目錄

一、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 的配置和管理都通過該屬性完成
nameSpring 容器同樣可以通過此屬性對容器中的 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 種方法實作初始化回呼和銷毀回呼:

  1. 實作 InitializingBean 和 DisposableBean 介面;
  2. 在 XML 中配置 init-method 和 destory-method;
  3. 使用 @PostConstruct 和 @PreDestory 注解,


在一個 Bean 中有多種生命周期回呼方法時,優先級為:注解 > 介面 > XML,

不建議使用介面和注解,這會讓 pojo 類和 Spring 框架緊耦合,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/395603.html

標籤:java

上一篇:如果包含jQuery檔案,為什么PHPPDObindParam回傳null

下一篇:如何從Prometheus服務器獲取按特定標簽過濾的所有指標名稱

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more