目錄
經典面試題目:
一,Bean的生命周期圖
二,關于Bean的生命周期流程介紹:
三,Bean的單例與多例模式
總結:
前言:今天小編給大家帶來的是關于Spring系列篇中的Bean的生命周期講解。在了解Bean的生命周期建議先看Spring 的AOP的講解。希望大家看了能夠對你們學習,工作帶來有效的幫助!Spring http://t.csdn.cn/N0Fp4http://t.csdn.cn/N0Fp4
經典面試題目:
問題一:“ Spring容器管理JavaBean的初始化流程?”
答:“ 第一步:在【xml,configuation 注解,annotation 配置類】中配置JavaBean
? ? ? ? ? 第二步:在BeanDefinitionReader中解析JavaBean生成BeanDefinition,通過list集合遍歷,。
? ? ? ? ? ?第三步:到BeanFactoryPostProcessor中,JavaBean執行自己的業務。
? ? ? ? ? ?第四步:spring中beanFactory,通過list集合初始化所有的Javabean對象。
? ? ? ? ? ?第五步:如果自己JavaBean需要調用spring上下文中的資源就需要實現*Aware感知接口。
? ? ? ? ? ?第六步:如果自己JavaBean已經初始化好了,則還要擴展。使用BeanFactoryPostProcessor來完成。
”
問題二:“ Spring中JavaBean是單例還是多例模式?”
答:“ 第一:Spring中JavaBean默認是單例模式的但可以配置成多例模式。因為:這根單例模式的特點有關:單例的特點:節約內存資源,變量容易污染。 多例的特點:占用大量資源,變量不易污染。”??
?????????第二:單例模式:JavaBean跟著上下文初始化的” 多例模式:JavaBean在使用時才創建的,銷毀跟著”
? ? ? ? ? 第三:第二點并不是絕對的。
一,Bean的生命周期圖
理解:Spring的生命周期主要指創建、初始化、銷毀。Bean的生命周期主要由容器進行管理,我們可以自定義bean的初始化和銷毀方法,容器在bean進行到生命周期的特定時間點,來調用自定義的初始化和銷毀方法。
二,關于Bean的生命周期流程介紹:
1. 通過XML、Java annotation以及Java Configuration等方式加載spring bean
2. BeanDefinitionReader:解析Bean的定義。Spring容器啟動的過程中,會將Bean解析成Spring內部的BeanDefinition結構;該過程有點類似于實例化后的建模對象。
3. BeanDefinition:包含了多少屬性和方法,例如類名、scope、屬性、構造函數參數列表、依賴的bean、是否是單例、是否是懶加載等。其實就是將Bean的定義信息存儲到這個BeanDefinition相應的屬性中,后面對Bean的操作就直接對BeanDefinition進行,例如拿到這個BeanDefinition后,可以根據里面的類名、構造函數、構造函數參數,使用反射進行對象創建。
思路:通過查看beandefinition的原碼,發現這個類中已經定義,封裝了它自己的類名、構造函數、構造函數參數,所以我們拿到它這個對象我們去遍歷依據反射原理可以得到實例的對象
? ?
4. BeanFactoryPostProcessor:是實現spring容器功能擴展的重要接口,例如修改bean屬性值,實現bean動態代理等。很多框架都是通過此接口實現對spring容器的擴展,例如mybatis與spring集成時,只定義了mapper接口,無實現類,但spring卻可以完成自動注入。
? ?> 注意:
? ?> 1)BeanFactoryPostProcessor在spring容器加載完BeanDefinition之后,在bean實例化之前執行的;
? ?> 2)對bean元數據(BeanDefinition)進行加工處理,也就是BeanDefinition屬性填充、修改等操作;??? ??? ?如果要對某個bean中的某個屬性進行非空驗證之類的操作(自定義操作),就可以實現該接口類
??? ??? ?BeanFactoryPostProcessor來完成擴展功能。5. BeanFactory:Bean工廠。它按照我們的要求,生產我們需要的各種各樣的bean,提供給我們使用。只是在生產bean的過程中,需要解決bean之間的依賴問題,才引入了依賴注入(DI)這種技術。也就是說依賴注入是beanFactory生產bean時為了解決bean之間的依賴的一種技術而已。
6)Aware感知接口:在實際開發中,經常需要用到Spring容器本身的功能資源
例如:BeanNameAware、ApplicationContextAware等等
BeanDefinition 實現了 BeanNameAware、ApplicationContextAware
7)BeanPostProcessor:后置處理器。在Bean對象實例化和引入注入完畢后,
在顯示調用初始化方法的前后添加自定義的邏輯。(類似于AOP的繞環通知)
前提條件:如果檢測到Bean對象實現了BeanPostProcessor后置處理器才會執行
Before和After方法
BeanPostProcessor
1)Before
2)調用初始化Bean(InitializingBean和init-method,Bean的初始化才算完成)
3)After
完成了Bean的創建工作
8)destory:銷毀
詳細介紹Bean的生命周期中單詞
1 BeanDefinitionReader
在Spring中,BeanDefinitionReader是用于讀取并解析配置文件的類,它在JavaBean的生命周期中起著重要的作用。在JavaBean的生命周期中,BeanDefinitionReader主要用于實例化和屬性注入階段。它會讀取配置文件中的<bean>標簽,并解析其中的屬性值、初始化方法和銷毀方法等信息。通過解析配置文件,BeanDefinitionReader可以獲取到JavaBean的類名、屬性值、初始化方法和銷毀方法等元數據。
在實例化階段,BeanDefinitionReader會根據配置文件中的信息使用反射機制創建JavaBean的實例。它會根據配置文件中的<bean>標簽中的class屬性獲取到JavaBean的類名,并使用反射機制創建JavaBean的實例。
在屬性注入階段,BeanDefinitionReader會根據配置文件中的<property>標簽獲取到JavaBean的屬性值,并使用反射機制將屬性值注入到JavaBean中。它會根據配置文件中的<property>標簽中的name屬性獲取到屬性名,然后根據name屬性獲取到對應的屬性值,并使用反射機制將屬性值注入到JavaBean中。
除了實例化和屬性注入階段,BeanDefinitionReader還可以在其他階段發揮作用。例如,在初始化階段,BeanDefinitionReader可以讀取配置文件中的init-method屬性,并將其作為初始化方法進行調用。在銷毀階段,BeanDefinitionReader可以讀取配置文件中的destroy-method屬性,并將其作為銷毀方法進行調用。
總之,BeanDefinitionReader在JavaBean的生命周期中起著解析和讀取配置文件的作用,它能夠獲取到JavaBean的元數據,并根據配置文件中的信息進行實例化、屬性注入、初始化和銷毀等操作。
2 BeanDefinition
BeanDefinition是Spring框架中的一個重要概念,它用于描述和定義一個Bean的信息。具體來說,BeanDefinition的作用主要有以下幾個方面:
1. 定義Bean的屬性:BeanDefinition定義了一個Bean的屬性,包括Bean的類名、作用域、是否懶加載、依賴關系等。通過BeanDefinition,可以對Bean的屬性進行配置和管理。
2. 描述Bean的依賴關系:BeanDefinition描述了Bean與其他Bean之間的依賴關系。它可以指定Bean所依賴的其他Bean,以及依賴的方式(如通過構造函數注入、setter方法注入等)。通過BeanDefinition,可以實現Bean之間的依賴注入。
3. 定義Bean的初始化和銷毀方法:BeanDefinition可以定義Bean的初始化方法和銷毀方法。它可以指定Bean在實例化之后需要執行的初始化方法,以及在銷毀之前需要執行的銷毀方法。通過BeanDefinition,可以實現對Bean生命周期的管理。
4. 擴展Bean的功能:通過BeanDefinition,可以對Bean的定義進行擴展,實現自定義的功能。可以在BeanDefinition中添加AOP切面、事務管理等功能,從而實現對Bean的增強。
5. 靈活配置Bean的定義:BeanDefinition提供了靈活的配置方式,可以通過XML配置文件、注解或編程的方式來定義Bean。可以根據需要,選擇合適的方式來配置Bean的定義。
總之,BeanDefinition是Spring框架中用于描述和定義Bean的信息的重要概念。它定義了Bean的屬性、依賴關系、初始化和銷毀方法等信息,可以實現對Bean的配置和管理。通過BeanDefinition,可以實現靈活的Bean配置和擴展,從而實現對Bean的定制化功能。3 BeanFactoryPostProcessor
BeanFactoryPostProcessor是Spring框架中的一個擴展接口,它可以在Spring容器實例化Bean之后,對Bean的定義進行修改或擴展。具體來說,BeanFactoryPostProcessor的作用主要有以下幾個方面:
1. 修改Bean的定義:通過實現BeanFactoryPostProcessor接口,可以在Spring容器實例化Bean之前,對Bean的定義進行修改。可以添加、刪除或修改Bean的屬性值、作用域、依賴關系等。這樣可以在不修改源代碼的情況下,對Bean的定義進行動態調整。
2. 擴展Bean的定義:通過實現BeanFactoryPostProcessor接口,可以在Spring容器實例化Bean之前,對Bean的定義進行擴展。可以添加新的Bean定義,或者通過修改Bean的定義來實現自定義的擴展功能。例如,可以在Bean的定義中添加AOP切面、事務管理等功能。
3. 配置Bean的屬性值:通過實現BeanFactoryPostProcessor接口,可以在Spring容器實例化Bean之前,對Bean的屬性值進行配置。可以根據需要,動態地設置Bean的屬性值,從而實現更靈活的配置。
4. 解析和處理Bean的定義:BeanFactoryPostProcessor接口還可以用于解析和處理Bean的定義。可以根據需要,對Bean的定義進行解析和處理,以實現特定的邏輯。例如,可以根據Bean的定義生成其他相關的Bean定義,或者根據Bean的定義進行一些邏輯判斷和處理。
需要注意的是,BeanFactoryPostProcessor是在Spring容器實例化Bean之后,對Bean的定義進行修改或擴展的。它與BeanPostProcessor接口的區別在于,BeanFactoryPostProcessor是在Bean的定義階段進行操作,而BeanPostProcessor是在Bean的實例化和初始化階段進行操作。因此,BeanFactoryPostProcessor可以對Bean的定義進行修改,而BeanPostProcessor只能對Bean的實例進行操作。4 BeanFactory
BeanFactory是Spring框架中的核心接口之一,它是用于管理和獲取Bean實例的工廠。具體來說,BeanFactory的作用主要有以下幾個方面:
1. 實例化Bean:BeanFactory負責根據配置文件或注解等方式,實例化JavaBean。它會根據配置文件中的<bean>標簽或注解中的配置信息,使用反射機制創建JavaBean的實例。通過BeanFactory,可以方便地創建和獲取各種類型的Bean實例。
2. 管理Bean的生命周期:BeanFactory管理著Bean的生命周期。它會在需要時創建Bean的實例,并在不需要時銷毀Bean的實例。通過BeanFactory,可以控制Bean的創建、初始化和銷毀等過程,實現對Bean的靈活管理。
3. 注入依賴關系:BeanFactory負責將Bean之間的依賴關系注入到Bean實例中。它會根據配置文件中的<property>標簽或注解中的依賴關系,將依賴的Bean注入到目標Bean中。通過BeanFactory,可以實現Bean之間的依賴注入,從而實現松耦合的設計。
4. 提供Bean的訪問接口:BeanFactory提供了訪問Bean的接口,可以方便地獲取已經實例化的Bean。通過BeanFactory,可以根據Bean的名稱或類型,獲取到對應的Bean實例。這樣可以方便地在應用程序中使用Bean,實現各種功能。
總之,BeanFactory是Spring框架中用于管理和獲取Bean實例的核心接口。它負責實例化Bean、管理Bean的生命周期、注入依賴關系和提供Bean的訪問接口等功能,是Spring框架中實現IoC(控制反轉)和DI(依賴注入)的重要組成部分。5 Aware
Aware是Spring框架中的一組接口,用于在Bean實例化過程中向Bean注入特定的資源或回調接口。具體來說,Aware接口主要有以下幾個作用:
1. 提供對Spring容器的訪問:通過實現ApplicationContextAware接口,Bean可以獲取對Spring容器的引用。這樣可以在Bean中直接訪問Spring容器的各種功能,如獲取其他Bean、獲取環境變量等。
2. 提供對BeanFactory的訪問:通過實現BeanFactoryAware接口,Bean可以獲取對BeanFactory的引用。這樣可以在Bean中直接訪問BeanFactory的各種功能,如獲取Bean的定義、獲取Bean的屬性等。
3. 提供對Bean的名稱的訪問:通過實現BeanNameAware接口,Bean可以獲取自己在Spring容器中的名稱。這樣可以在Bean中獲取自己的名稱,做一些特定的處理。
4. 提供對資源的訪問:通過實現ResourceLoaderAware接口,Bean可以獲取對資源加載器的引用。這樣可以在Bean中直接加載資源,如讀取配置文件、訪問文件等。
5. 提供對消息源的訪問:通過實現MessageSourceAware接口,Bean可以獲取對消息源的引用。這樣可以在Bean中直接訪問消息源,實現國際化和本地化的功能。
通過實現這些Aware接口,Bean可以獲取到Spring容器的相關資源或回調接口,從而實現對這些資源的訪問或使用。這樣可以在Bean中更方便地實現一些特定的功能,提高系統的靈活性和可擴展性。
?
三,Bean的單例與多例模式
單例與多例模式對比單例的特點:節約資源,變量容易污染。多例的特點:占用大量資源,變量不易污染。
通過演示代碼運行:
Spring使用單例模式的主要優點和好處包括:
1. 節省資源:單例模式可以確保在整個應用程序中只有一個實例存在,節省了系統資源的開銷。每次請求都返回同一個實例,避免了重復創建對象的開銷。
2. 提高性能:由于單例模式只創建一個實例,避免了頻繁的創建和銷毀對象的開銷,從而提高了系統的性能。
3. 避免競爭條件:在多線程環境下,使用單例模式可以避免多個線程同時訪問和修改對象的狀態,從而避免了競爭條件和數據不一致的問題。
4. 統一管理和協調資源:單例模式可以統一管理和協調系統中的共享資源,確保資源的正確使用和釋放,避免資源泄漏和浪費。
5. 提供全局訪問點:單例模式可以提供一個全局的訪問點,方便其他對象或模塊通過該訪問點來獲取實例,簡化了對象的使用和調用。
6. 簡化配置和管理:在Spring框架中,將Bean定義為單例模式可以簡化配置和管理,只需要在配置文件或注解中聲明為單例即可,Spring容器負責創建和管理單例對象。
總的來說,Spring使用單例模式的優點包括節省資源、提高性能、避免競爭條件、統一管理和協調資源、提供全局訪問點以及簡化配置和管理。這些優點使得Spring在處理大規模應用和高并發環境下表現出色,并且提供了更好的可擴展性和可維護性。
?
在Spring框架中,多例模式(Prototype Pattern)是指每次獲取對象實例時都會創建一個新的實例,相比于單例模式,多例模式具有以下優點和好處:
1. 靈活性:多例模式可以根據需求創建多個實例,每個實例可以有不同的狀態和屬性,提供了更大的靈活性和定制性。
2. 避免共享狀態:多例模式每次創建新的實例,避免了多個對象之間共享狀態的問題。每個實例都是獨立的,互不影響。
3. 高并發性能:在高并發環境下,多例模式可以減少線程競爭,提高系統的并發性能。每個線程獲取到的都是獨立的實例,不會出現資源競爭的情況。
4. 避免單例模式的缺點:單例模式在某些場景下可能會存在線程安全問題、資源占用過多等缺點,而多例模式可以避免這些問題。
5. 降低耦合度:多例模式可以降低對象之間的耦合度,每個對象都是獨立的,可以獨立創建和銷毀,不會產生過多的依賴關系。
6. 提供靈活的生命周期管理:多例模式可以通過Spring容器的生命周期管理功能來管理實例的創建和銷毀,提供了更靈活的生命周期管理方式。
需要注意的是,多例模式也存在一些潛在的問題,比如對象的創建和銷毀開銷較大,可能會影響系統性能;多例模式可能會導致對象的過度創建,占用過多的系統資源。因此,在使用多例模式時需要根據具體的業務場景和性能需求進行權衡和選擇。
?
1.spring.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"><bean id="paramAction" class="com.zking.beanLife.ParamAction" scope="prototype"><constructor-arg name="name" value="牛媽肥鏢"></constructor-arg><constructor-arg name="age" value="21"></constructor-arg><constructor-arg name="hobby"><list><value>抽煙</value><value>玩及</value><value>彩筆</value></list></constructor-arg></bean><bean id="instanceFactory" class="com.zking.beanLife.InstanceFactory"scope="prototype" init-method="init" destroy-method="destroy"></bean> </beans>
2.Demo測試類
package com.zking.beanLife;import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource;/** spring bean的生命週期* spring bean的單例多例*/ public class Demo2 {// 體現單例與多例的區別@Testpublic void test1() {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring.xml"); // ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");System.out.println(p1==p2);p1.execute();p2.execute();// 單例時,容器銷毀instanceFactory對象也銷毀;多例時,容器銷毀對象不一定銷毀;applicationContext.close();}// 體現單例與多例的初始化的時間點 instanceFactory@Testpublic void test2() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring.xml");}// BeanFactory會初始化bean對象,但會根據不同的實現子類采取不同的初始化方式// 默認情況下bean的初始化,單例模式立馬會執行,但是此時XmlBeanFactory作為子類,單例模式下容器創建,bean依賴沒有初始化,只有要獲取使用bean對象才進行初始化@Testpublic void test3() {// ClassPathXmlApplicationContext applicationContext = new// ClassPathXmlApplicationContext("/spring-context.xml");Resource resource = new ClassPathResource("/spring.xml");BeanFactory beanFactory = new XmlBeanFactory(resource); // InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");}}
這里單例模式改成多例模式只要在spring.xml中指定即可
演示效果:
單例模式運行結果:
?多例模式運行結果:?
3.單例模式和多例模式的適用場景
單例模式和多例模式在不同的場景下具有不同的適用性。以下是它們常見的適用場景:適用于單例模式的場景:
資源共享:當需要在應用程序的多個組件之間共享同一份資源或數據時,單例模式可以確保全局范圍內的數據一致性。
工廠類:當需要創建一個全局工廠類來統一管理對象的創建和生命周期時,單例模式可以確保該工廠類始終只有一個實例。
配置信息:當需要在應用程序中加載一份全局的配置信息,并且多個組件需要共享該配置信息時,單例模式可以確保配置信息的一致性和高效訪問。
日志記錄器:當需要在整個應用程序中使用同一個日志記錄器來記錄日志時,單例模式可以確保日志的一致性和集中管理。
適用于多例模式的場景:并發請求處理:當需要在多線程或并發環境下處理請求,并且每個請求使用獨立的實例來保證狀態隔離時,多例模式可以為每個請求創建一個獨立的對象。
對象池:當需要管理一組可復用的對象,并且對象在不同的時刻需要創建和銷毀時,多例模式可以提供對象池來管理對象的生命周期,以減少創建和銷毀的開銷。
狀態管理:當對象的狀態需要在不同的上下文環境中獨立維護和處理時,多例模式可以為每個上下文環境創建一個獨立的實例,以避免狀態沖突和相互干擾。
服務提供者:當系統需要支持多個相同類型的服務提供者,并且每個服務提供者需要獨立的實例時,多例模式可以滿足服務提供者的創建和管理需求。
?
總結:
Spring框架的生命周期主要包括創建、初始化和銷毀三個階段。通過容器管理Bean的生命周期,可以自定義Bean的初始化和銷毀方法,在特定的時間點由容器來調用。單實例Bean的整個生命周期都可以進行控制。Spring Bean的生命周期分為四個階段和多個擴展點。擴展點可以影響多個Bean或單個Bean的生命周期。總之,Spring框架提供了靈活的生命周期管理機制,使得開發者能夠更好地控制和定制Bean的創建和銷毀過程