Spirng 當中 Bean的作用域 @目錄Spirng 當中 Bean的作用域每博一文案1. Spring6 當中的 Bean的作用域1.2 singleton 預設1.3 prototype1.4 Spring 中的 bean 標簽當中scope= 屬性其他的值說明1.5 自定義作用域,一個線程 ...
Spirng 當中 Bean的作用域
@
目錄每博一文案
青年,青年!無論受怎樣的挫折和打擊,都要咬著牙關挺住,因為你們完全有機會重建生活;只要不灰心喪氣,每一次挫折就只不過是通往新境界的一塊普通絆腳石,而絕不會置人於死命
_____路遙《平凡的世界》
飛機上鄰座的姐姐
獨自一人坐飛機去見異地的男友
異地戀赤誠的人好像越來越少
我不自覺地問她
如果以後分手了不會覺得可惜麽
她一邊低頭和男友報備自己落座了
一邊回答說“我不是確認了不會分手才去愛他的,我恰恰是因為確定了我們有可能會分手才更要
用力去愛他的,更何況,人是用來擁有的,不是嗎”
———————《網友評論》
1. Spring6 當中的 Bean的作用域
1.2 singleton 預設
預設情況下,Spring的IoC容器創建的Bean對象是單例的。
我們來檢驗一下:
首先,方便大家處理,下麵明確出對應相關的 maven配置信息pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rainbowsea</groupId>
<artifactId>spring6-007-circular-dependency</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.11</version>
</dependency>
<!-- junit4 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
對應配置的 bean 的類是 User 這個類 ,為了方便辨析,簡單明瞭,這個 類,就不設置屬性了。就是一個空空的類。
package com.rainbowsea.spirngBean;
public class User {
public User() {
System.out.println("User() 的無參數構成方法");
}
}
配置 Spring框架當中的xml
配置文件,讓 Spring 知道我們的 User 這個類,併進行管理
<?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">
<bean name="user" class="com.rainbowsea.spirngBean.User"></bean>
</beans>
下麵編寫測試:代碼,進行一個測試,驗證,Spring 預設是否是 單例的 。這裡我們啟動多線程,進行一個測試
package com.ranbowsea.test;
import com.rainbowsea.spirngBean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testScope {
@Test
public void test01() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
User user = applicationContext.getBean("user", User.class);
User user1 = applicationContext.getBean("user", User.class);
System.out.println(user);
System.out.println(user1);
// 啟動線程
new Thread(new Runnable() {
@Override
public void run() {
User user2 = applicationContext.getBean("user", User.class);
User user3 = applicationContext.getBean("user", User.class);
System.out.println(user2);
System.out.println(user3);
}
}).start();
}
}
從結果上看:
- 無參構造方法僅僅只被調用了一次
- 四個user對象,的地址是一樣的
說明:無論是執行多少次,
applicationContext.getBean
,還是啟動多個線程,都是同一個User對象. 是單例的
這個對象在什麼時候創建的呢?可以為SpringBean提供一個無參數構造方法,測試一下,如下:
從結果上來看:是在
new ClassPathXmlApplicationContext()
的時候就已經,執行了構造方法(Bean對象的創建是在初始化Spring上下文的時候就完成的。)
其中: singleton
是Spring框架 預設的,也是單例的。
我們可以使用:可以在bean標簽中指定 scope
屬性的值為 singleton 。我們測試如下。
<?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">
<bean name="user" class="com.rainbowsea.spirngBean.User" scope="singleton"></bean>
</beans>
通過測試得知,沒有指定scope屬性時,預設是
singleton
單例的。
1.3 prototype
如果想讓Spring的Bean對象以多例
的形式存在,可以在bean標簽中指定 scope
屬性的值為:prototype,這樣Spring會在每一次執行getBean()方法的時候創建Bean對象,調用幾次則創建幾次。
<?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">
<bean name="user" class="com.rainbowsea.spirngBean.User" scope="prototype"></bean>
</beans>
我們來是:用 User 這個類進行測試,使用:
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testScope {
@Test
public void test() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
User user = applicationContext.getBean("user", User.class);
User user1 = applicationContext.getBean("user", User.class);
System.out.println(user);
System.out.println(user1);
}
}
從結果上看:
1.調用了兩次無參數構成方法()
2.是兩個不同的 user對象的地址
啟動多個線程,也是會存在多個,user對象的地址的,同時調用多次無參數構成方法()——> 是多例 的。 不像 singleton(預設)
的那樣是無論是執行多少次,applicationContext.getBean
,還是啟動多個線程,都是同一個User對象單例的。
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testScope {
@Test
public void test() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
User user = applicationContext.getBean("user", User.class);
User user1 = applicationContext.getBean("user", User.class);
System.out.println(user);
System.out.println(user1);
// 啟動多線程
new Thread(new Runnable() {
@Override
public void run() {
User user2 = applicationContext.getBean("user", User.class);
User user3 = applicationContext.getBean("user", User.class);
System.out.println(user2);
System.out.println(user3);
}
}).start();
}
}
1.4 Spring 中的 bean 標簽當中scope= 屬性其他的值說明
scope屬性的值不止兩個,它一共包括8個選項:
- singleton:預設的,單例。
- prototype:原型。每調用一次getBean()方法則獲取一個新的Bean對象。或每次註入的時候都是新對象。
- request:一個請求對應一個Bean。僅限於在WEB應用中使用。
- session:一個會話對應一個Bean。僅限於在WEB應用中使用。
- global session:portlet應用中專用的。如果在Servlet的WEB應用中使用global session的話,和session一個效果。(portlet和servlet都是規範。servlet運行在servlet容器中,例如Tomcat。portlet運行在portlet容器中。)
- application:一個應用對應一個Bean。僅限於在WEB應用中使用。
- websocket:一個websocket生命周期對應一個Bean。僅限於在WEB應用中使用。
- 自定義scope:很少使用。
特殊說明: 如果大家,進行了一個實踐測試代碼,可能會發現,IDE工具,僅僅只提示了 scope屬性值的兩個值(singleton,prototype)。就算我們自己手動敲出了其他的值,也是會報紅 。如下圖所示:
哈哈哈,這個IDE不給我們提示就算了,還給我們報錯。
其實這個並不是IDE工具的問題,而是,我們其他的對應的scope其他屬性的值,是需要在特定的情況下才有用的。比如:我們這裡的
request
是需要在web
項目當中才是有用的 ,所以 IDE才給我們來了這麼一個錯誤——》爆紅了。
我們可以,在 pom.xml
項目配置文件上,加上一個web 框架,比如:這裡我們加上SpringMVC
就可以了。試試
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rainbowsea</groupId>
<artifactId>spring6-007-circular-dependency</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.11</version>
</dependency>
<!-- junit4 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
</dependencies>
</project>
1.5 自定義作用域,一個線程一個 Bean
接下來咱們自定義一個Scope,關於線程級別的Scope,
作用:在同一個線程中,獲取的Bean都是同一個。跨線程則是不同的對象。
第一步:自定義Scope。(實現Scope介面)
spring內置了線程範圍的類:
org.springframework.beans.factory.config.CustomScopeConfigurer
,和org.springframework.context.support.SimpleThreadScope
可以直接用。
- 第二步:將自定義的Scope註冊到Spring容器中。
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="myThread">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
<?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">
<!-- 自定義一個 scope屬性值:作用:在同一個線程中,獲取的Bean都是同一個。跨線程則是不同的對象。-->
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes"> <!-- set 註入,為該類當中的 name 屬性賦值-->
<map> <!-- map集合 註入,為該類當中的 key 屬性賦值,也就是我們自定義的 scope的屬性值的名字-->
<entry key="myThread">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
<bean name="user" class="com.rainbowsea.spirngBean.User" scope="myThread"></bean>
</beans>
我們還是使用 User 這個類,作為 Bean 進行一個測試。
啟動多個線程,處理。
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testScope {
@Test
public void test() {
// 第一個線程
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
User user = applicationContext.getBean("user", User.class);
User user1 = applicationContext.getBean("user", User.class);
System.out.println(user);
System.out.println(user1);
// 啟動多線程
// 第二個線程
new Thread(new Runnable() {
@Override
public void run() {
User user2 = applicationContext.getBean("user", User.class);
User user3 = applicationContext.getBean("user", User.class);
System.out.println(user2);
System.out.println(user3);
}
}).start();
}
}
從結果上,我們可以看出:
一個線程,調用了一次無參構造方法(),生產一個對象。
成功實現了。在同一個線程中,獲取的Bean都是同一個。跨線程則是不同的對象。
2. 總結:
- 預設情況下,Spring的IoC容器創建的Bean對象是單例的。預設是singleton(單例的)
- 可以在bean標簽中指定scope屬性的值為:**prototype(多例),預設是singleton(單例的) **
- 同時要註意:scope屬性的值不止兩個,它一共包括8個選項:,其他的要在特定的配置下,才能使用,例如:request和session 要是在
web
框架才可以使用。
3. 最後:
“在這個最後的篇章中,我要表達我對每一位讀者的感激之情。你們的關註和回覆是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮鬥。感謝你們,我們總會在某個時刻再次相遇。”