自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring如何管理Bean的生命周期呢?

開發(fā) 前端
對于非單例 Bean(如 prototype 作用域的 Bean),它們會(huì)在每次請求時(shí)創(chuàng)建,并在不再需要時(shí)由 Java 的垃圾回收機(jī)制銷毀。

我們都知道,在面試的過程中,關(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 的生命周期了么?

責(zé)任編輯:武曉燕 來源: Java極客技術(shù)
相關(guān)推薦

2022-10-19 23:28:55

Spring生命周期Bean

2023-12-28 09:59:37

Spring容器XML

2021-12-08 11:18:21

Spring Bean面試題生命周期

2022-03-14 08:54:42

SpringBean生命周期

2020-02-10 19:34:12

生命周期流程流程圖

2022-09-05 07:06:59

BeanSpring

2012-06-20 10:29:16

敏捷開發(fā)

2021-07-19 05:52:29

網(wǎng)絡(luò)生命周期網(wǎng)絡(luò)框架

2022-06-01 09:25:16

嵌套生命周期智能技術(shù)工業(yè)資產(chǎn)

2011-04-19 09:27:25

Spring

2015-07-08 16:28:23

weak生命周期

2024-03-14 10:47:12

Spring生命周期阿里

2020-12-11 08:04:22

SpringAOPBean

2009-05-21 09:12:41

Java開發(fā)平臺(tái)生命周期管理

2020-06-10 07:38:30

Spring框架周期

2022-04-21 14:03:54

開發(fā)API生命周期

2018-01-18 10:08:27

零部件

2022-04-19 07:20:24

軟件開發(fā)安全生命周期SSDLC應(yīng)用安全

2010-05-17 22:06:41

數(shù)據(jù)安全電子文檔鼎普科技

2020-03-13 07:33:28

物聯(lián)網(wǎng)生命周期管理IOT
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號