一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

解析加載及實(shí)例化Bean的順序(零配置)

5jek_harmonyos ? 來(lái)源:CSDN ? 作者:低調(diào)的JVM ? 2021-08-04 16:08 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

作者丨低調(diào)的JVM

來(lái)自丨CSDN

https://blog.csdn.net/qq_27529917/article/details/79329809

在使用Spring時(shí),Bean之間會(huì)有些依賴(lài),比如一個(gè)Bean A實(shí)例化時(shí)需要用到Bean B,那么B應(yīng)該在A之前實(shí)例化好。很多時(shí)候Spring智能地為我們做好了這些工作,但某些情況下可能不是,比如Springboot的@AutoConfigureAfter注解,手動(dòng)的指定Bean的實(shí)例化順序。

了解Spring內(nèi)Bean的解析,加載和實(shí)例化順序機(jī)制有助于我們更好的使用Spring/Springboot,避免手動(dòng)的去干預(yù)Bean的加載過(guò)程,搭建更優(yōu)雅的框架。

Spring容器在實(shí)例化時(shí)會(huì)加載容器內(nèi)所有非延遲加載的單例類(lèi)型Bean,看如下源碼:

public abstract class AbstractApplicationContext extends DefaultResourceLoader

implements ConfigurableApplicationContext, DisposableBean {

//刷新Spring容器,相當(dāng)于初始化

public void refresh() throws BeansException, IllegalStateException {

。。。。。。

// Instantiate all remaining (non-lazy-init) singletons.

finishBeanFactoryInitialization(beanFactory);

}

}

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory

implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

/** List of bean definition names, in registration order */

private volatile List《String》 beanDefinitionNames = new ArrayList《String》(256);

public void preInstantiateSingletons() throws BeansException {

List《String》 beanNames = new ArrayList《String》(this.beanDefinitionNames);

for (String beanName : beanNames) {

。。。。。。

getBean(beanName); //實(shí)例化Bean

}

}

}

ApplicationContext內(nèi)置一個(gè)BeanFactory對(duì)象,作為實(shí)際的Bean工廠,和Bean相關(guān)業(yè)務(wù)都交給BeanFactory去處理。

在BeanFactory實(shí)例化所有非延遲加載的單例Bean時(shí),遍歷beanDefinitionNames 集合,按順序?qū)嵗付Q(chēng)的Bean。beanDefinitionNames 屬性是Spring在加載Bean Class生成的BeanDefinition時(shí),為這些Bean預(yù)先定義好的名稱(chēng),看如下代碼:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory

implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

throws BeanDefinitionStoreException {

。。。。。。

this.beanDefinitionNames.add(beanName);

}

}

BeanFactory在加載一個(gè)BeanDefinition(也就是加載Bean Class)時(shí),將相應(yīng)的beanName存入beanDefinitionNames屬性中,在加載完所有的BeanDefinition后,執(zhí)行Bean實(shí)例化工作,此時(shí)會(huì)依據(jù)beanDefinitionNames的順序來(lái)有序?qū)嵗疊ean,也就是說(shuō)Spring容器內(nèi)Bean的加載和實(shí)例化是有順序的,而且近似一致,當(dāng)然僅是近似。

Spring在初始化容器時(shí),會(huì)先解析和加載所有的Bean Class,如果符合要求則通過(guò)Class生成BeanDefinition,存入BeanFactory中,在加載完所有Bean Class后,開(kāi)始有序的通過(guò)BeanDefinition實(shí)例化Bean。

我們先看加載Bean Class過(guò)程,零配置下Spring Bean的加載起始于ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)方法,我總結(jié)了下其加載解析Bean Class的流程:

配置類(lèi)可以是Spring容器的起始配置類(lèi),也可以是通過(guò)@ComponentScan掃描得到的類(lèi),也可以是通過(guò)@Import引入的類(lèi)。如果這個(gè)類(lèi)上含有@Configuration,@Component,@ComponentScan,@Import,@ImportResource注解中的一個(gè),或者內(nèi)部含有@Bean標(biāo)識(shí)的方法,那么這個(gè)類(lèi)就是一個(gè)配置類(lèi),Spring就會(huì)按照一定流程去解析這個(gè)類(lèi)上的信息。

在解析的第一步會(huì)校驗(yàn)當(dāng)前類(lèi)是否已經(jīng)被解析過(guò)了,如果是,那么需要按照一定的規(guī)則處理(@ComponentScan得到的Bean能覆蓋@Import得到的Bean,@Bean定義的優(yōu)先級(jí)最高)。

如果未解析過(guò),那么開(kāi)始解析:

解析內(nèi)部類(lèi),查看內(nèi)部類(lèi)是否應(yīng)該被定義成一個(gè)Bean,如果是,遞歸解析。

解析@PropertySource,也就是解析被引入的Properties文件。

解析配置類(lèi)上是否有@ComponentScan注解,如果有則執(zhí)行掃描動(dòng)作,通過(guò)掃描得到的Bean Class會(huì)被立即解析成BeanDefinition,添加進(jìn)beanDefinitionNames屬性中。之后查看掃描到的Bean Class是否是一個(gè)配置類(lèi)(大部分情況是,因?yàn)闃?biāo)識(shí)@Component注解),如果是則遞歸解析這個(gè)Bean Class。

解析@Import引入的類(lèi),如果這個(gè)類(lèi)是一個(gè)配置類(lèi),則遞歸解析。

解析@Bean標(biāo)識(shí)的方法,此種形式定義的Bean Class不會(huì)被遞歸解析

解析父類(lèi)上的@ComponentScan,@Import,@Bean,父類(lèi)不會(huì)被再次實(shí)例化,因?yàn)槠渥宇?lèi)能夠做父類(lèi)的工作,不需要額外的Bean了。

在1,3,4,6中都有遞歸操作,也就是在解析一個(gè)Bean Class A時(shí),發(fā)現(xiàn)其上能夠獲取到其他Bean Class B信息,此時(shí)會(huì)遞歸的解析Bean Class B,在解析完Bean Class B后再接著解析Bean Class A,可能在解析B時(shí)能夠獲取到C,那么也會(huì)先解析C再解析B,就這樣不斷的遞歸解析。

在第3步中,通過(guò)@ComponentScan掃描直接得到的Bean Class會(huì)被立即加載入beanDefinitionNames中,但@Import和@Bean形式定義的Bean Class則不會(huì),也就是說(shuō)正常情況下面@ComponentScan直接得到的Bean其實(shí)例化時(shí)機(jī)比其他兩種形式的要早。

通過(guò)@Bean和@Import形式定義的Bean Class不會(huì)立即加載,他們會(huì)被放入一個(gè)ConfigurationClass類(lèi)中,然后按照解析的順序有序排列,就是圖片上的 “將配置類(lèi)有序排列”。一個(gè)ConfigurationClass代表一個(gè)配置類(lèi),這個(gè)類(lèi)可能是被@ComponentScan掃描到的,則此類(lèi)已經(jīng)被加載過(guò)了;也可能是被@Import引入的,則此類(lèi)還未被加載;此類(lèi)中可能含有@Bean標(biāo)識(shí)的方法。

Spring在解析完了所有Bean Class后,開(kāi)始加載ConfigurationClass。如果這個(gè)ConfigurationClass是被Import的,也就是說(shuō)在加載@ComponentScan時(shí)其未被加載,那么此時(shí)加載ConfigurationClass代表的Bean Class。然后加載ConfigurationClass內(nèi)的@Bean方法。

順序總結(jié):@ComponentScan 》 @Import 》 @Bean

Bean Class的結(jié)構(gòu)圖如上所示,A是配置類(lèi)的入口,通過(guò)A能直接或間接的引入一個(gè)模塊。

此時(shí)啟動(dòng)Spring容器,將A引入容器內(nèi)。

如果A是通過(guò)@ComponentScan掃描到的,那么此時(shí)的加載順序是:

A 》 D 》 F 》 B 》 E 》 G 》 C

如果A是通過(guò)@Import形式引入的,那么此時(shí)的加載順訊是:

D 》 F 》 B 》 E 》 G 》 A 》 C

當(dāng)然以上僅僅代表著加載Bean Class的順序,實(shí)際實(shí)例化Bean的順序和加載順序大體相同,但還是會(huì)有一些差別。

Spring在通過(guò)getBean(beanName)形式實(shí)例化Bean時(shí),會(huì)通過(guò)BeanDefinition去生成Bean對(duì)象。在這個(gè)過(guò)程中,如果BeanDefinition的DependsOn不為空,從字面理解就是依賴(lài)某個(gè)什么,其值一般是某個(gè)或多個(gè)beanName,也就是說(shuō)依賴(lài)于其他Bean。

此時(shí)Spring會(huì)將DependsOn指定的這些名稱(chēng)的Bean先實(shí)例化,也就是先調(diào)用getBean(dependsOn)方法。我們可以通過(guò)在Bean Class或者@Bean的方法上標(biāo)識(shí)**@DependsOn**注解,來(lái)指定當(dāng)前Bean實(shí)例化時(shí)需要觸發(fā)哪些Bean的提前實(shí)例化。

當(dāng)一個(gè)Bean A內(nèi)部通過(guò)@Autowired或者@Resource注入Bean B,那么在實(shí)例化A時(shí)會(huì)觸發(fā)B的提前實(shí)例化,此時(shí)會(huì)注冊(cè)A》B的dependsOn依賴(lài)關(guān)系,實(shí)質(zhì)和@DependsOn一樣,這個(gè)是Spring自動(dòng)為我們處理好的。

了解Spring Bean的解析,加載及實(shí)例化的順序機(jī)制能夠加深對(duì)Spring的理解,搭建更優(yōu)雅簡(jiǎn)介的Spring框架。

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    15082

原文標(biāo)題:Spring解析,加載及實(shí)例化Bean的順序(零配置)

文章出處:【微信號(hào):harmonyos_developer,微信公眾號(hào):harmonyos_developer】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    鴻蒙5開(kāi)發(fā)寶藏案例分享---Web加載時(shí)延優(yōu)化解析

    : Network泳道 :查看資源加載時(shí)序 Main泳道 :監(jiān)控JS/CSS解析阻塞 Performance面板 :定位長(zhǎng)任務(wù)(Long Tasks) ??** 四大優(yōu)化方向 + 代碼實(shí)戰(zhàn)** 以下
    發(fā)表于 06-12 17:11

    請(qǐng)問(wèn)CCyUSBDevice如何同時(shí)實(shí)例2個(gè)?

    CYAPI編程手冊(cè)中的解釋?zhuān)珻CyUSBDevice實(shí)例后是連接到了cyusb driver驅(qū)動(dòng)上,它能查找實(shí)例中的多臺(tái)USB設(shè)備?,F(xiàn)在的問(wèn)題是假如我有2臺(tái)cyusb3014設(shè)備,固件一樣,系統(tǒng)
    發(fā)表于 05-19 07:27

    使用DAC34H84 datasheet提供的參考上電配置順序同步不了,datasheet上提供的同步順序還有問(wèn)題?

    的。 使用的是雙同步源模式,ISTR同步FIFO的寫(xiě)指針,OSTR(PLL的N分頻)同步FIFO的讀指針。SYNC同步PLL的N分頻器。 1、使用DAC34H84 datasheet提供的參考上電配置順序
    發(fā)表于 01-15 07:12

    如何選擇合適的云服務(wù)器 --X 實(shí)例購(gòu)買(mǎi)指南和配置詳細(xì)說(shuō)明

    前言 ? 1 x實(shí)例介紹 ? 2 購(gòu)買(mǎi)步驟 ? 2.1 登錄華為云官網(wǎng) ? 2.2 Flexus云服務(wù)器X實(shí)例頁(yè)面 ? 2.3 配置服務(wù)器 ? 2.4 購(gòu)買(mǎi)服務(wù)器 ? 3 X實(shí)例
    的頭像 發(fā)表于 12-24 17:27 ?676次閱讀
    如何選擇合適的云服務(wù)器 --X <b class='flag-5'>實(shí)例</b>購(gòu)買(mǎi)指南和<b class='flag-5'>配置</b>詳細(xì)說(shuō)明

    SSM框架的源碼解析與理解

    的核心是控制反轉(zhuǎn)(IoC)和面向切面編程(AOP)。 源碼解析: Spring的源碼主要分為以下幾個(gè)部分: Bean容器: 負(fù)責(zé)實(shí)例、配置
    的頭像 發(fā)表于 12-17 09:20 ?989次閱讀

    自動(dòng)創(chuàng)建UI并解析數(shù)據(jù)

    *附件:32960_auto.rar備注:Main.vi是ui自動(dòng)2.1.vi,配置文件為32960.B.ini。 目前可以實(shí)現(xiàn)根據(jù)配置文件自動(dòng)創(chuàng)建控件并布局,且可以自動(dòng)
    發(fā)表于 12-10 08:41

    DP83869HM使用100m光口模式時(shí),需要配置哪些寄存器和配置順序呢?

    驅(qū)動(dòng),還是需要自己修改使其全部訪問(wèn)間接地址(c00開(kāi)始的) 使用100m光口模式時(shí),需要配置哪些寄存器和配置順序呢?謝謝!
    發(fā)表于 12-05 07:10

    自動(dòng)創(chuàng)建UI并解析數(shù)據(jù)

    Labview實(shí)現(xiàn)動(dòng)態(tài)增加控件效果 - *附件:32960_auto.rar 備注:Main.vi是ui自動(dòng)2.1.vi,配置文件為32960.B.ini。 目前可以實(shí)現(xiàn)根據(jù)配置文件自動(dòng)
    發(fā)表于 11-29 11:26

    請(qǐng)問(wèn)LMX2595配置時(shí)如何進(jìn)行初始

    您好,查閱手冊(cè)說(shuō)初始按照1.r0的rest置為1;2.r0的reset置為1;3.按照寄存器表格配置寄存器;4.fcal_en置為1的順序來(lái)初始。請(qǐng)問(wèn)在第三步中,按照寄存器表
    發(fā)表于 11-12 06:51

    LMK04832的寄存器配置順序嗎?

    大家好,請(qǐng)問(wèn)該芯片的寄存器配置順序嗎?只要按照TICS軟件中的配置順序就行了嗎?
    發(fā)表于 11-11 08:31

    SpringBean初始順序

    Spring bean是Spring框架在運(yùn)行時(shí)管理的對(duì)象。Spring bean是任何Spring應(yīng)用程序的基本構(gòu)建塊。我們編寫(xiě)的大多數(shù)應(yīng)用程序邏輯代碼都將放在Spring bean中。 執(zhí)行
    的頭像 發(fā)表于 11-06 16:04 ?435次閱讀
    SpringBean初始<b class='flag-5'>化</b><b class='flag-5'>順序</b>

    低功耗模組短信通:短消息發(fā)送實(shí)例解析

    今天帶大家學(xué)習(xí)的是低功耗4G模組發(fā)送SMS短消息的解析,以Air780E為實(shí)例,讓大家了解更透徹。 SMS(短消息服務(wù),ShortMessageService)功能主要用于在蜂窩網(wǎng)絡(luò)中傳輸短消息。 移動(dòng),聯(lián)通卡不需開(kāi)通VOLTE可以支持短信功能。
    的頭像 發(fā)表于 10-29 14:43 ?1951次閱讀
    低功耗模組短信通:短消息發(fā)送<b class='flag-5'>實(shí)例</b><b class='flag-5'>解析</b>

    labview實(shí)現(xiàn)DBC在界面加載配置

    labview實(shí)現(xiàn)DBC在界面加載配置
    發(fā)表于 08-19 14:27 ?39次下載

    labview CAN DBC加載解析程序

    labview CAN DBC加載解析程序
    發(fā)表于 08-18 11:42

    【電磁兼容標(biāo)準(zhǔn)解析分享】汽車(chē)電子部件EMC標(biāo)準(zhǔn)解析---你應(yīng)該了解和知道的細(xì)節(jié)(二)

    【電磁兼容標(biāo)準(zhǔn)解析分享】汽車(chē)電子部件EMC標(biāo)準(zhǔn)解析---你應(yīng)該了解和知道的細(xì)節(jié)(二)
    的頭像 發(fā)表于 08-08 08:17 ?6321次閱讀
    【電磁兼容標(biāo)準(zhǔn)<b class='flag-5'>解析</b>分享】汽車(chē)電子<b class='flag-5'>零</b>部件EMC標(biāo)準(zhǔn)<b class='flag-5'>解析</b>---你應(yīng)該了解和知道的細(xì)節(jié)(二)