Spring如何管理Bean的生命周期呢?
我們都知道,在面試的過程中,關(guān)于 Spring 的面試題,那是各種各樣,很多時(shí)候就會(huì)問到關(guān)于 Spring的相關(guān)問題,比如 AOP ,IOC 等等,還有就是關(guān)于 Spring 是如何管理 Bean 的生命周期的相關(guān)問題,今天了不起就來和大家一起看看 Spring 是如何管理 Bean 的生命周期的。
源碼分析
BeanFactory
其實(shí)我們對于這個(gè) Spring 管理 Bean 的生命周期有時(shí)候并不需要我們?nèi)ゴ笃娜ケ痴b某塊的內(nèi)容,我們需要的就是學(xué)會(huì)看源代碼,比如源代碼中的注釋部分,當(dāng)我們看到這注釋部分的時(shí)候,很大程度上能夠幫助我們理解源碼的含義。
BeanFactory是Spring框架中的一個(gè)接口,它是一個(gè)工廠類,用來創(chuàng)建和管理Spring中的Bean對象。
我們看源碼中的注釋
* <p>Bean factory implementations should support the standard bean lifecycle interfaces
* as far as possible. The full set of initialization methods and their standard order is:
這句話直接翻譯就是 Bean Factory 實(shí)現(xiàn)類應(yīng)該盡可能的支持標(biāo)準(zhǔn)的生命周期接口。注釋的下半段內(nèi)容,就是描述的 Bean 生命周期的相關(guān)內(nèi)容了。所以源碼里面的注釋需要我們及時(shí)的去看一下,雖然都是純英文的,但是能讀出個(gè)大概得內(nèi)容,再去看源碼的話,至少知道它是干嘛的方法。
Bean 的生命周期
我們在了解他如何管理的時(shí)候,我們得先知道這個(gè) Bean 的生命周期都有哪幾個(gè)階段,知道了階段,我們再來看它的實(shí)現(xiàn)。
我們先總結(jié):
Bean 的生命周期可以總結(jié)為如下的幾個(gè)階段,
1. Bean的實(shí)例化階段
2. Bean的設(shè)置屬性階段
3. Bean的 初始化階段
4. Bean的銷毀階段
也有些人會(huì)細(xì)分實(shí)例化階段,就是把實(shí)例化拆分成兩部分,第一部分是注冊階段,第二部分是實(shí)例化階段,其實(shí)區(qū)別不大。
Bean實(shí)例化階段
在Spring框架中,Bean的實(shí)例化是一個(gè)核心過程,它涉及了多個(gè)步驟以確保Bean能夠正確地被創(chuàng)建并注入到應(yīng)用上下文中。
Bean定義注冊:
- 首先,你需要在Spring的配置文件(如XML配置文件或Java配置類)中定義Bean。這包括指定Bean的類名、作用域、初始化方法、銷毀方法以及可能的依賴關(guān)系等。
- Spring容器會(huì)讀取這些配置,并將Bean定義信息存儲(chǔ)在其內(nèi)部的數(shù)據(jù)結(jié)構(gòu)中,通常是BeanDefinition對象。
實(shí)例化前的準(zhǔn)備:
- 在實(shí)例化Bean之前,Spring會(huì)進(jìn)行一些準(zhǔn)備工作,如解析Bean定義中的屬性、檢查依賴關(guān)系等。
- 如果Bean定義中引用了其他Bean,Spring會(huì)嘗試先解析并實(shí)例化這些依賴Bean。
實(shí)例化:
- 實(shí)例化是創(chuàng)建Bean對象的過程。Spring提供了多種實(shí)例化Bean的方式:
構(gòu)造器實(shí)例化:通過調(diào)用Bean的構(gòu)造方法來創(chuàng)建實(shí)例。你可以在配置文件中指定要使用的構(gòu)造方法,并提供相應(yīng)的參數(shù)。
靜態(tài)工廠方法實(shí)例化:通過調(diào)用靜態(tài)工廠方法來創(chuàng)建Bean實(shí)例。你需要在配置文件中指定工廠類的類名和工廠方法的名稱。
實(shí)例工廠方法實(shí)例化:首先實(shí)例化一個(gè)工廠Bean,然后調(diào)用該工廠Bean的某個(gè)非靜態(tài)方法來創(chuàng)建目標(biāo)Bean實(shí)例。
默認(rèn)構(gòu)造器實(shí)例化:如果Bean定義中沒有指定其他實(shí)例化方式,并且Bean類有一個(gè)無參構(gòu)造器,那么Spring將使用默認(rèn)構(gòu)造器來實(shí)例化Bean。
- 實(shí)例化完成后,你得到的是一個(gè)原始的對象,它還沒有進(jìn)行任何屬性注入或初始化。
屬性注入:
- 在Bean實(shí)例化之后,Spring會(huì)進(jìn)行屬性注入(也稱為依賴注入)。這包括將Bean定義中指定的屬性值或?qū)ζ渌鸅ean的引用注入到Bean的相應(yīng)屬性中。
- Spring支持多種屬性注入方式,如基于字段的注入、基于setter方法的注入和基于構(gòu)造器的注入等。
BeanPostProcessor處理:
在Bean的屬性注入完成后,但Bean的初始化方法執(zhí)行之前,Spring會(huì)調(diào)用已注冊的BeanPostProcessor接口的postProcessBeforeInitialization方法。這是一個(gè)可選的步驟,你可以通過實(shí)現(xiàn)該接口并注冊相應(yīng)的BeanPostProcessor來在Bean初始化前后執(zhí)行自定義的邏輯。
初始化:
- 接下來,Spring會(huì)調(diào)用Bean定義中指定的初始化方法(如果有的話)。這通常是在Bean類中定義的某個(gè)方法,并用特定的注解(如@PostConstruct)或XML配置中的元素的init-method屬性來指定。
- 初始化方法是Bean在準(zhǔn)備好接受請求之前進(jìn)行必要設(shè)置或執(zhí)行特定任務(wù)的地方。
BeanPostProcessor再處理:
在Bean初始化方法執(zhí)行之后,Spring會(huì)再次調(diào)用已注冊的BeanPostProcessor接口的postProcessAfterInitialization方法。這是另一個(gè)可選的步驟,你可以在這里執(zhí)行一些清理或后處理操作。
Bean就緒:
經(jīng)過上述步驟后,Bean就已經(jīng)被完全創(chuàng)建并初始化了?,F(xiàn)在它可以被應(yīng)用上下文中的其他組件使用或注入到其他Bean中。
到這里,我們的實(shí)例化就說完了,記下來看第二階段。
Bean的設(shè)置屬性階段
Bean的設(shè)置屬性階段(也稱為屬性注入或依賴注入)是Bean生命周期中的一個(gè)重要環(huán)節(jié)。這個(gè)階段發(fā)生在Spring容器創(chuàng)建Bean的實(shí)例之后,但在Bean被實(shí)際使用之前。
- 當(dāng)Spring容器創(chuàng)建一個(gè)Bean的實(shí)例后,它會(huì)檢查該Bean是否有需要注入的屬性。這些屬性可能是其他的Bean、基本數(shù)據(jù)類型、集合、Map等。
- Spring會(huì)查找與這些屬性對應(yīng)的配置信息(可能是XML中的標(biāo)簽、注解中的值或其他配置方式),并將它們注入到Bean的相應(yīng)字段或setter方法中。
注入方式:
- 字段注入:通過直接在字段上使用@Autowired或其他相關(guān)注解來實(shí)現(xiàn)。但請注意,字段注入在某些情況下可能導(dǎo)致測試?yán)щy或難以遵循良好的封裝原則。
- 構(gòu)造函數(shù)注入:在構(gòu)造函數(shù)參數(shù)上使用@Autowired或其他相關(guān)注解。這是推薦的方式之一,因?yàn)樗_保了Bean在創(chuàng)建時(shí)就已經(jīng)擁有所有必需的依賴項(xiàng),并且這些依賴項(xiàng)是不可變的。
- setter方法注入:在setter方法上使用@Autowired或其他相關(guān)注解。這種方式允許Bean在創(chuàng)建后的某個(gè)時(shí)間點(diǎn)接收其依賴項(xiàng)。
既然我們已經(jīng)把這個(gè)屬性設(shè)置完畢了,那么就要開始后進(jìn)行初始化階段了。
Bean 的初始化
- Bean Aware接口回調(diào)
- Bean初始化前操作
- Bean初始化操作
- Bean初始化后操作
- Bean初始化完成操作
BeanAware接口回調(diào)
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
Bean初始化前操作
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
Bean初始化操作
調(diào)用InitializingBean接口的afterPropertiesSet方法 調(diào)用定義bean的時(shí)候指定的初始化方法。
public interface InitializingBean {
/**
* Invoked by the containing {@code BeanFactory} after it has set all bean properties
* and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
* <p>This method allows the bean instance to perform validation of its overall
* configuration and final initialization when all bean properties have been set.
* @throws Exception in the event of misconfiguration (such as failure to set an
* essential property) or if initialization fails for any other reason
*/
void afterPropertiesSet() throws Exception;
}
Bean初始化后階段
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
Bean初始化完成操作
public interface SmartInitializingSingleton {
/**
* Invoked right at the end of the singleton pre-instantiation phase,
* with a guarantee that all regular singleton beans have been created
* already. {@link ListableBeanFactory#getBeansOfType} calls within
* this method won't trigger accidental side effects during bootstrap.
* <p><b>NOTE:</b> This callback won't be triggered for singleton beans
* lazily initialized on demand after {@link BeanFactory} bootstrap,
* and not for any other bean scope either. Carefully use it for beans
* with the intended bootstrap semantics only.
*/
void afterSingletonsInstantiated();
}
當(dāng)我們完成了初始化之后,使用完成,最后 Bean 就要走到銷毀階段了。
Bean 的銷毀
@Override
public void destroyBean(Object existingBean) {
new DisposableBeanAdapter(
existingBean, getBeanPostProcessorCache().destructionAware, getAccessControlContext()).destroy();
}
這里需要注意的是
- 當(dāng)容器關(guān)閉時(shí),或者當(dāng)單例 Bean 的作用域結(jié)束時(shí),Spring 會(huì)銷毀 Bean 的實(shí)例。
- 對于非單例 Bean(如 prototype 作用域的 Bean),它們會(huì)在每次請求時(shí)創(chuàng)建,并在不再需要時(shí)由 Java 的垃圾回收機(jī)制銷毀。
你知道 Spring是如何管理 Bean 的生命周期了么?