【SpringBean】bean的作用域和bean的生命周期

目錄

前言

一 bean的作用域

1. singleton——唯一 bean 實例

2. prototype——每次請求都會創建一個新的 bean 實例

3. request——每一次HTTP請求都會產生一個新的bean,該bean僅在當前HTTP request內有效

4. session——每一次HTTP請求都會產生一個新的 bean,該bean僅在當前 HTTP session 內有效

5. globalSession

二 bean的生命周期

initialization 和 destroy

實現*Aware接口 在Bean中使用Spring框架的一些對象

BeanPostProcessor

總結

單例管理的對象

非單例管理的對象


前言

在 Spring 中,那些組成應用程序的主體及由 Spring IOC 容器所管理的對象,被稱之為 bean。簡單地講,bean 就是由 IOC 容器初始化、裝配及管理的對象,除此之外,bean 就與應用程序中的其他對象沒有什么區別了。而 bean 的定義以及 bean 相互間的依賴關系將通過配置元數據來描述。

Spring中的bean默認都是單例的,這些單例Bean在多線程程序下如何保證線程安全呢? 例如對于Web應用來說,Web容器對于每個用戶請求都創建一個單獨的Sevlet線程來處理請求,引入Spring框架之后,每個Action都是單例的,那么對于Spring托管的單例Service Bean,如何保證其安全呢? Spring的單例是基于BeanFactory也就是Spring容器的,單例Bean在此容器內只有一個,Java的單例是基于 JVM,每個 JVM 內只有一個實例。

在大多數情況下。單例 bean 是很理想的方案。不過,有時候你可能會發現你所使用的類是易變的,它們會保持一些狀態,因此重用是不安全的。在這種情況下,將 class 聲明為單例的就不是那么明智了。因為對象會被污染,稍后重用的時候會出現意想不到的問題。所以 Spring 定義了多種作用域的bean。

一 bean的作用域

創建一個bean定義,其實質是用該bean定義對應的類來創建真正實例的“配方”。把bean定義看成一個配方很有意義,它與class很類似,只根據一張“處方”就可以創建多個實例。不僅可以控制注入到對象中的各種依賴和配置值,還可以控制該對象的作用域。這樣可以靈活選擇所建對象的作用域,而不必在Java Class級定義作用域。Spring Framework支持五種作用域,分別闡述如下表。

五種作用域中,request、sessionglobal session 三種作用域僅在基于web的應用中使用(不必關心你所采用的是什么web應用框架),只能用在基于 web 的 Spring ApplicationContext 環境。

1. singleton——唯一 bean 實例

當一個 bean 的作用域為 singleton,那么Spring IoC容器中只會存在一個共享的 bean 實例,并且所有對 bean 的請求,只要 id 與該 bean 定義相匹配,則只會返回bean的同一實例。 singleton 是單例類型(對應于單例模式),就是在創建起容器時就同時自動創建了一個bean的對象,不管你是否使用,但我們可以指定Bean節點的 lazy-init=”true” 來延遲初始化bean,這時候,只有在第一次獲取bean時才會初始化bean,即第一次請求該bean時才初始化。 每次獲取到的對象都是同一個對象。注意,singleton 作用域是Spring中的缺省作用域。要在XML中將 bean 定義成 singleton ,可以這樣配置:

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">

也可以通過 @Scope 注解(它可以顯示指定bean的作用范圍。)的方式

@Service
@Scope("singleton")
public class ServiceImpl{
?
}

2. prototype——每次請求都會創建一個新的 bean 實例

當一個bean的作用域為 prototype,表示一個 bean 定義對應多個對象實例。 prototype 作用域的 bean 會導致在每次對該 bean 請求(將其注入到另一個 bean 中,或者以程序的方式調用容器的 getBean() 方法)時都會創建一個新的 bean 實例。prototype 是原型類型,它在我們創建容器的時候并沒有實例化,而是當我們獲取bean的時候才會去創建一個對象,而且我們每次獲取到的對象都不是同一個對象。根據經驗,對有狀態的 bean 應該使用 prototype 作用域,而對無狀態的 bean 則應該使用 singleton 作用域。 在 XML 中將 bean 定義成 prototype ,可以這樣配置:

<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/> ?
 或者
<bean id="account" class="com.foo.DefaultAccount" singleton="false"/> 

通過 @Scope 注解的方式實現就不做演示了。

3. request——每一次HTTP請求都會產生一個新的bean,該bean僅在當前HTTP request內有效

request只適用于Web程序,每一次 HTTP 請求都會產生一個新的bean,同時該bean僅在當前HTTP request內有效,當請求結束后,該對象的生命周期即告結束。 在 XML 中將 bean 定義成 request ,可以這樣配置:

<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>

4. session——每一次HTTP請求都會產生一個新的 bean,該bean僅在當前 HTTP session 內有效

session只適用于Web程序,session 作用域表示該針對每一次 HTTP 請求都會產生一個新的 bean,同時該 bean 僅在當前 HTTP session 內有效.與request作用域一樣,可以根據需要放心的更改所創建實例的內部狀態,而別的 HTTP session 中根據 userPreferences 創建的實例,將不會看到這些特定于某個 HTTP session 的狀態變化。當HTTP session最終被廢棄的時候,在該HTTP session作用域內的bean也會被廢棄掉。

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

5. globalSession

global session 作用域類似于標準的 HTTP session 作用域,不過僅僅在基于 portlet 的 web 應用中才有意義。Portlet 規范定義了全局 Session 的概念,它被所有構成某個 portlet web 應用的各種不同的 portle t所共享。在global session 作用域中定義的 bean 被限定于全局portlet Session的生命周期范圍內。

 

二 bean的生命周期

Spring Bean是Spring應用中最最重要的部分了。所以來看看Spring容器在初始化一個bean的時候會做那些事情,順序是怎樣的,在容器關閉的時候,又會做哪些事情。

spring版本:4.2.3.RELEASE 鑒于Spring源碼是用gradle構建的,我也決定舍棄我大maven,嘗試下洪菊推薦過的gradle。運行beanLifeCycle模塊下的junit test即可在控制臺看到如下輸出,可以清楚了解Spring容器在創建,初始化和銷毀Bean的時候依次做了那些事情。

Spring容器初始化
=====================================
調用GiraffeService無參構造函數
GiraffeService中利用set方法設置屬性值
調用setBeanName:: Bean Name defined in context=giraffeService
調用setBeanClassLoader,ClassLoader Name = sun.misc.Launcher$AppClassLoader
調用setBeanFactory,setBeanFactory:: giraffe bean singleton=true
調用setEnvironment
調用setResourceLoader:: Resource File Name=spring-beans.xml
調用setApplicationEventPublisher
調用setApplicationContext:: Bean Definition Names=[giraffeService, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0, com.giraffe.spring.service.GiraffeServicePostProcessor#0]
執行BeanPostProcessor的postProcessBeforeInitialization方法,beanName=giraffeService
調用PostConstruct注解標注的方法
執行InitializingBean接口的afterPropertiesSet方法
執行配置的init-method
執行BeanPostProcessor的postProcessAfterInitialization方法,beanName=giraffeService
Spring容器初始化完畢
=====================================
從容器中獲取Bean
giraffe Name=李光洙
=====================================
調用preDestroy注解標注的方法
執行DisposableBean接口的destroy方法
執行配置的destroy-method
Spring容器關閉

先來看看,Spring在Bean從創建到銷毀的生命周期中可能做得事情。

initialization 和 destroy

有時我們需要在Bean屬性值set好之后和Bean銷毀之前做一些事情,比如檢查Bean中某個屬性是否被正常的設置好值了。Spring框架提供了多種方法讓我們可以在Spring Bean的生命周期中執行initialization和pre-destroy方法。

1.實現InitializingBean和DisposableBean接口

這兩個接口都只包含一個方法。通過實現InitializingBean接口的afterPropertiesSet()方法可以在Bean屬性值設置好之后做一些操作,實現DisposableBean接口的destroy()方法可以在銷毀Bean之前做一些操作。

例子如下:

public class GiraffeService implements InitializingBean,DisposableBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("執行InitializingBean接口的afterPropertiesSet方法");}@Overridepublic void destroy() throws Exception {System.out.println("執行DisposableBean接口的destroy方法");}
}

這種方法比較簡單,但是不建議使用。因為這樣會將Bean的實現和Spring框架耦合在一起。

2.在bean的配置文件中指定init-method和destroy-method方法

Spring允許我們創建自己的 init 方法和 destroy 方法,只要在 Bean 的配置文件中指定 init-method 和 destroy-method 的值就可以在 Bean 初始化時和銷毀之前執行一些操作。

例子如下:

public class GiraffeService {//通過<bean>的destroy-method屬性指定的銷毀方法public void destroyMethod() throws Exception {System.out.println("執行配置的destroy-method");}//通過<bean>的init-method屬性指定的初始化方法public void initMethod() throws Exception {System.out.println("執行配置的init-method");}
}

配置文件中的配置:

<bean name="giraffeService" class="com.giraffe.spring.service.GiraffeService" init-method="initMethod" destroy-method="destroyMethod">
</bean>

需要注意的是自定義的init-method和post-method方法可以拋異常但是不能有參數。

這種方式比較推薦,因為可以自己創建方法,無需將Bean的實現直接依賴于spring的框架。

3.使用@PostConstruct和@PreDestroy注解

除了xml配置的方式,Spring 也支持用 @PostConstruct@PreDestroy注解來指定 initdestroy 方法。這兩個注解均在javax.annotation 包中。為了注解可以生效,需要在配置文件中定義org.springframework.context.annotation.CommonAnnotationBeanPostProcessor或context:annotation-config

例子如下:

public class GiraffeService {@PostConstructpublic void initPostConstruct(){System.out.println("執行PostConstruct注解標注的方法");}@PreDestroypublic void preDestroy(){System.out.println("執行preDestroy注解標注的方法");}
}

配置文件:

 ?
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
?

實現*Aware接口 在Bean中使用Spring框架的一些對象

有些時候我們需要在 Bean 的初始化中使用 Spring 框架自身的一些對象來執行一些操作,比如獲取 ServletContext 的一些參數,獲取 ApplicaitionContext 中的 BeanDefinition 的名字,獲取 Bean 在容器中的名字等等。為了讓 Bean 可以獲取到框架自身的一些對象,Spring 提供了一組名為*Aware的接口。

這些接口均繼承于org.springframework.beans.factory.Aware標記接口,并提供一個將由 Bean 實現的set*方法,Spring通過基于setter的依賴注入方式使相應的對象可以被Bean使用。 網上說,這些接口是利用觀察者模式實現的,類似于servlet listeners,目前還不明白,不過這也不在本文的討論范圍內。 介紹一些重要的Aware接口:

  • ApplicationContextAware: 獲得ApplicationContext對象,可以用來獲取所有Bean definition的名字。

  • BeanFactoryAware:獲得BeanFactory對象,可以用來檢測Bean的作用域。

  • BeanNameAware:獲得Bean在配置文件中定義的名字。

  • ResourceLoaderAware:獲得ResourceLoader對象,可以獲得classpath中某個文件。

  • ServletContextAware:在一個MVC應用中可以獲取ServletContext對象,可以讀取context中的參數。

  • ServletConfigAware: 在一個MVC應用中可以獲取ServletConfig對象,可以讀取config中的參數。

public class GiraffeService implements ? ApplicationContextAware,ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware,BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware{@Overridepublic void setBeanClassLoader(ClassLoader classLoader) {System.out.println("執行setBeanClassLoader,ClassLoader Name = " + classLoader.getClass().getName());}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("執行setBeanFactory,setBeanFactory:: giraffe bean singleton=" + ?beanFactory.isSingleton("giraffeService"));}@Overridepublic void setBeanName(String s) {System.out.println("執行setBeanName:: Bean Name defined in context="+ s);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("執行setApplicationContext:: Bean Definition Names="+ Arrays.toString(applicationContext.getBeanDefinitionNames()));}@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {System.out.println("執行setApplicationEventPublisher");}@Overridepublic void setEnvironment(Environment environment) {System.out.println("執行setEnvironment");}@Overridepublic void setResourceLoader(ResourceLoader resourceLoader) {Resource resource = resourceLoader.getResource("classpath:spring-beans.xml");System.out.println("執行setResourceLoader:: Resource File Name="+ resource.getFilename());}@Overridepublic void setImportMetadata(AnnotationMetadata annotationMetadata) {System.out.println("執行setImportMetadata");}
}

BeanPostProcessor

上面的*Aware接口是針對某個實現這些接口的Bean定制初始化的過程, Spring同樣可以針對容器中的所有Bean,或者某些Bean定制初始化過程,只需提供一個實現BeanPostProcessor接口的類即可。 該接口中包含兩個方法,postProcessBeforeInitialization和postProcessAfterInitialization。 postProcessBeforeInitialization方法會在容器中的Bean初始化之前執行, postProcessAfterInitialization方法在容器中的Bean初始化之后執行。

例子如下:

public class CustomerBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("執行BeanPostProcessor的postProcessBeforeInitialization方法,beanName=" + beanName);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("執行BeanPostProcessor的postProcessAfterInitialization方法,beanName=" + beanName);return bean;}
}

要將BeanPostProcessor的Bean像其他Bean一樣定義在配置文件中

<bean class="com.giraffe.spring.service.CustomerBeanPostProcessor"/>

總結

所以。。。結合第一節控制臺輸出的內容,Spring Bean的生命周期是這樣紙的:

  • Bean容器找到配置文件中 Spring Bean 的定義。

  • Bean容器利用Java Reflection API創建一個Bean的實例。

  • 如果涉及到一些屬性值 利用set方法設置一些屬性值。

  • 如果Bean實現了BeanNameAware接口,調用setBeanName()方法,傳入Bean的名字。

  • 如果Bean實現了BeanClassLoaderAware接口,調用setBeanClassLoader()方法,傳入ClassLoader對象的實例。

  • 如果Bean實現了BeanFactoryAware接口,調用setBeanFactory()方法,傳入BeanFactory對象的實例。

  • 與上面的類似,如果實現了其他*Aware接口,就調用相應的方法。

  • 如果有和加載這個Bean的Spring容器相關的BeanPostProcessor對象,執行postProcessBeforeInitialization()方法

  • 如果Bean實現了InitializingBean接口,執行afterPropertiesSet()方法。

  • 如果Bean在配置文件中的定義包含init-method屬性,執行指定的方法。

  • 如果有和加載這個Bean的Spring容器相關的BeanPostProcessor對象,執行postProcessAfterInitialization()方法

  • 當要銷毀Bean的時候,如果Bean實現了DisposableBean接口,執行destroy()方法。

  • 當要銷毀Bean的時候,如果Bean在配置文件中的定義包含destroy-method屬性,執行指定的方法。

用圖表示一下(圖來源:http://www.jianshu.com/p/d00539babca5):

與之比較類似的中文版本:

其實很多時候我們并不會真的去實現上面說描述的那些接口,那么下面我們就除去那些接口,針對bean的單例和非單例來描述下bean的生命周期:

單例管理的對象

當scope=”singleton”,即默認情況下,會在啟動容器時(即實例化容器時)時實例化。但我們可以指定Bean節點的lazy-init=”true”來延遲初始化bean,這時候,只有在第一次獲取bean時才會初始化bean,即第一次請求該bean時才初始化。如下配置:

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" lazy-init="true"/> ?

如果想對所有的默認單例bean都應用延遲初始化,可以在根節點beans設置default-lazy-init屬性為true,如下所示:

<beans default-lazy-init="true" …>

默認情況下,Spring 在讀取 xml 文件的時候,就會創建對象。在創建對象的時候先調用構造器,然后調用 init-method 屬性值中所指定的方法。對象在被銷毀的時候,會調用 destroy-method 屬性值中所指定的方法(例如調用Container.destroy()方法的時候)。寫一個測試類,代碼如下:

public class LifeBean {private String name; ?
?public LifeBean(){ ?System.out.println("LifeBean()構造函數"); ?} ?public String getName() { ?return name; ?} ?
?public void setName(String name) { ?System.out.println("setName()"); ?this.name = name; ?} ?
?public void init(){ ?System.out.println("this is init of lifeBean"); ?} ?
?public void destory(){ ?System.out.println("this is destory of lifeBean " + this); ?} ?
}

 life.xml配置如下:

<bean id="life_singleton" class="com.bean.LifeBean" scope="singleton" init-method="init" destroy-method="destory" lazy-init="true"/>

測試代碼:

public class LifeTest {@Test public void test() {AbstractApplicationContext container = new ClassPathXmlApplicationContext("life.xml");LifeBean life1 = (LifeBean)container.getBean("life");System.out.println(life1);container.close();}
}

運行結果:

LifeBean()構造函數
this is init of lifeBean
com.bean.LifeBean@573f2bb1
……
this is destory of lifeBean com.bean.LifeBean@573f2bb1

非單例管理的對象

scope=”prototype”時,容器也會延遲初始化 bean,Spring 讀取xml 文件的時候,并不會立刻創建對象,而是在第一次請求該 bean 時才初始化(如調用getBean方法時)。在第一次請求每一個 prototype 的bean 時,Spring容器都會調用其構造器創建這個對象,然后調用init-method屬性值中所指定的方法。對象銷毀的時候,Spring 容器不會幫我們調用任何方法,因為是非單例,這個類型的對象有很多個,Spring容器一旦把這個對象交給你之后,就不再管理這個對象了。

為了測試prototype bean的生命周期life.xml配置如下:

<bean id="life_prototype" class="com.bean.LifeBean" scope="prototype" init-method="init" destroy-method="destory"/>

測試程序:

public class LifeTest {@Test public void test() {AbstractApplicationContext container = new ClassPathXmlApplicationContext("life.xml");LifeBean life1 = (LifeBean)container.getBean("life_singleton");System.out.println(life1);
?LifeBean life3 = (LifeBean)container.getBean("life_prototype");System.out.println(life3);container.close();}
}

運行結果:

LifeBean()構造函數
this is init of lifeBean
com.bean.LifeBean@573f2bb1
LifeBean()構造函數
this is init of lifeBean
com.bean.LifeBean@5ae9a829
……
this is destory of lifeBean com.bean.LifeBean@573f2bb1

可以發現,對于作用域為 prototype 的 bean ,其destroy方法并沒有被調用。如果 bean 的 scope 設為prototype時,當容器關閉時,destroy 方法不會被調用。對于 prototype 作用域的 bean,有一點非常重要,那就是 Spring不能對一個 prototype bean 的整個生命周期負責:容器在初始化、配置、裝飾或者是裝配完一個prototype實例后,將它交給客戶端,隨后就對該prototype實例不聞不問了。 不管何種作用域,容器都會調用所有對象的初始化生命周期回調方法。但對prototype而言,任何配置好的析構生命周期回調方法都將不會被調用。清除prototype作用域的對象并釋放任何prototype bean所持有的昂貴資源,都是客戶端代碼的職責(讓Spring容器釋放被prototype作用域bean占用資源的一種可行方式是,通過使用bean的后置處理器,該處理器持有要被清除的bean的引用)。談及prototype作用域的bean時,在某些方面你可以將Spring容器的角色看作是Java new操作的替代者,任何遲于該時間點的生命周期事宜都得交由客戶端來處理。

Spring 容器可以管理 singleton 作用域下 bean 的生命周期,在此作用域下,Spring 能夠精確地知道bean何時被創建,何時初始化完成,以及何時被銷毀。而對于 prototype 作用域的bean,Spring只負責創建,當容器創建了 bean 的實例后,bean 的實例就交給了客戶端的代碼管理,Spring容器將不再跟蹤其生命周期,并且不會管理那些被配置成prototype作用域的bean的生命周期。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/714749.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714749.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714749.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

程序員的金三銀四求職寶典!

目錄 ?編輯 程序員的金三銀四求職寶典 一、為什么金三銀四是程序員求職的黃金時期&#xff1f; 二、如何準備金三銀四求職&#xff1f; 1. 完善簡歷 2. 增強技術能力 3. 提前考慮目標公司 4. 提前準備面試 三、程序員求職的常見面試題 1. 數據結構和算法 2. 數據庫 …

一次電腦感染Synaptics Pointing Device Driver病毒的經歷,分享下經驗

沒想到作為使用電腦多年的老司機也會電腦中病毒&#xff0c;周末玩電腦的時候突然電腦很卡&#xff0c;然后自動重啟&#xff0c;奇怪&#xff0c;之前沒出現這個情況。 重啟后電腦開機等了幾十秒&#xff0c;打開任務管理器查看開機進程&#xff0c;果然發現有個Synaptics Po…

LeetCode 刷題 [C++] 第121題.買賣股票的最佳時機

題目描述 給定一個數組 prices &#xff0c;它的第 i 個元素 prices[i] 表示一支給定股票第 i 天的價格。 你只能選擇 某一天 買入這只股票&#xff0c;并選擇在 未來的某一個不同的日子 賣出該股票。設計一個算法來計算你所能獲取的最大利潤。 返回你可以從這筆交易中獲取的…

php兒童服裝銷售管理系統計算機畢業設計項目包運行調試

php mysql兒童服裝銷售網 功能&#xff1a;前臺后臺 前臺&#xff1a; 1.服裝資訊 文章標題列表 詳情 2.服裝選購中心 分頁查看圖文列表 詳情 3.用戶注冊 登陸 退出 4.服裝加入收藏 5.加入購物車 6.對服裝進行評論 會員中心&#xff1a; 1.我的賬戶 查看 修改 2.我的收藏 查看 …

STM32 中斷流程介紹

STM32可以產生中斷的事件多種多樣&#xff0c;比如&#xff1a;定時器時間結束、串口接收到數據、某個GPIO檢測到電平變化等等等等。 1、STM32 gpio 中斷處理流程介紹 1、從引腳進入的高低電平首先由輸入驅動器處理&#xff0c;如下圖 2、經過輸入驅動器處理后的信號會進…

大數據數據平臺的數倉體系分類有哪些?

大數據平臺的數倉體系最初由數據庫發展而來&#xff0c;主要分為三類架構&#xff0c;分別是Shared-Nothing、Shared-Data、Shared-Everything。 Shared-Nothing&#xff08;也稱 MPP&#xff09;架構在 很長一段時間成為主流。 隨云原生能力增強&#xff0c;Snowflake 為代表…

c++基礎知識補充4

單獨使用詞匯 using std::cout; 隱式類型轉換型初始化&#xff1a;如A a1,,此時可以形象地理解為int i1;double ji;&#xff0c;此時1可以認為創建了一個值為1的臨時對象&#xff0c;然后對目標對象進行賦值&#xff0c;當對象為多參數時&#xff0c;使用&#xff08;1&#xf…

c1-周考2

c1-第二周 9月-技能1.一個島上有兩種神奇動物&#xff0c;其中神奇鳥類2個頭3只腳&#xff0c;神奇獸類3個頭8只腳。游客在濃霧中看到一群動物&#xff0c;共看到35個頭和110只腳&#xff0c;求可能的鳥類和獸類的只數2.構建一個長度為5的數組&#xff0c;并且實現下列要求3.構…

鬼屋游戲c++

c #include <iostream> #include <string> #include <vector> #include <cstdlib> // 用于隨機數生成 #include <ctime> // 用于隨機數種子using namespace std;// 定義房間結構體 struct Room {string description;bool hasKey;bool hasClue…

babylonjs入門-自由相機 FreeCamera

基于babylonjs封裝的一些功能和插件 &#xff0c;希望有更多的小伙伴一起玩babylonjs&#xff1b; 歡迎加群&#xff08;點擊群號傳送&#xff09;&#xff1a;464146715 官方文檔 中文文檔 案例傳送門 懶得打字 粘貼復制 一氣呵成 ?

計算機網絡——22TCP擁塞

TCP擁塞 TCP擁塞控制機制 端到端的擁塞控制機制 路由器不向主機有關擁塞的反饋信息 路由器的負擔較輕符合網絡核心簡單的TCP/IP架構原則 端系統根據自身得到的信息&#xff0c;判斷是否發生擁塞&#xff0c;從而采取動作 擁塞控制的幾個問題 如何檢測擁塞 輕微擁塞擁塞 控…

javascript在現實中的應用

JavaScript是一種非常強大的編程語言&#xff0c;在現實世界中有廣泛的應用。它最初被設計用于網頁交互&#xff0c;但隨著時間的發展&#xff0c;其用途已經大大擴展。以下是JavaScript在現實中的一些主要應用&#xff1a; 1. **網頁開發**: - **前端開發**: JavaScript是…

Http基礎之http協議、無狀態協議、狀態碼、http報文、跨域-cors

Http基礎 HTTP基礎HTTP協議請求方法持久連接管線化 無狀態協議使用Cookie狀態管理 狀態碼1XX2XX OK200 OK204 NO Content206 Content-Range 3XX 重定向301302304307 4XX400401403404 5XX500503 HTTP報文請求報文響應報文通用首部字段Cache-ControlConnectionDate請求首部字段Ac…

智能時代的領航者:人工智能的前沿探索

智能時代的領航者&#xff1a;人工智能的前沿探索 人工智能的定義與發展歷程 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是指通過模擬、延伸人類智能的理論、方法、技術及應用系統&#xff0c;以實現智能化的機器或軟件。人工智能的發展經歷了符…

Linux系統中已經可用的重要的網絡和故障排除命令

在Linux系統中&#xff0c;網絡設置、問題查找和故障修復是系統管理的重要技能&#xff0c;對于開發人員來說&#xff0c;了解Linux故障排除命令對于日常任務十分有幫助。 本文將介紹在Linux系統中已經可用的重要的網絡和故障排除命令。 以下是已經存在于Linux機器上的故障排…

2024可以實現月入過萬的抖店,適合新手做嗎?

我是電商珠珠 過完年了&#xff0c;一些新手都在找項目&#xff0c;覺得自己能做的項目很少。每個人身邊或多或少都有做電商的人&#xff0c;都說做電商可以年入百萬什么的&#xff0c;于是找到了抖店&#xff0c;但是對于抖店并不了解&#xff0c;不知道抖店適不適合自己。 …

JVM 第四部分—垃圾回收相關概念 2

System.gc() 在默認情況下&#xff0c;通過System.gc()或者Runtime.getRuntime().gc()的調用&#xff0c;會顯式觸發Full GC&#xff0c;同時對老年代和新生代進行回收&#xff0c;嘗試釋放被丟棄對象占用的內存 然而System.gc()調用附帶一個免責聲明&#xff0c;無法保證對垃…

博途PLC 面向對象系列之“雙通氣缸功能塊“(SCL代碼)

1、面向對象系列之找對象 https://rxxw-control.blog.csdn.net/article/details/136150027https://rxxw-control.blog.csdn.net/article/details/1361500272、博途PLC 面向對象系列之"單通氣缸功能塊" https://rxxw-control.blog.csdn.net/article/details/1363399…

如何使用pip安裝和生成requirements.txt

使用 pip freeze 命令可以列出當前環境中已安裝的所有 Python 包及其版本信息&#xff0c;并將其輸出保存到 requirements.txt 文件中。可以使用重定向 (>) 將命令的輸出寫入文件中 pip freeze > requirements.txt使用 pip install 命令可以從 requirements.txt 文件中安…

Spark(1)-wordCount入門

1. 創建Maven項目 <?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/P…