日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

11 张流程图帮你搞定 Spring Bean 生命周期 (核心)

發(fā)布時(shí)間:2025/3/20 javascript 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 11 张流程图帮你搞定 Spring Bean 生命周期 (核心) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

點(diǎn)擊上方?好好學(xué)java?,選擇?星標(biāo)?公眾號(hào)

重磅資訊、干貨,第一時(shí)間送達(dá)

今日推薦:騰訊推出高性能 RPC 開(kāi)發(fā)框架

個(gè)人原創(chuàng)100W+訪問(wèn)量博客:點(diǎn)擊前往,查看更多

來(lái)源:www.jianshu.com/p/70b935f2b3fe

在網(wǎng)上已經(jīng)有跟多Bean的生命周期的博客,但是很多都是基于比較老的版本了,最近把整個(gè)流程化成了一個(gè)流程圖。待會(huì)兒使用流程圖,說(shuō)明以及代碼的形式來(lái)說(shuō)明整個(gè)聲明周期的流程。注意因?yàn)榇a比較多,這里的流程圖只畫(huà)出了大概的流程,具體的可以深入代碼。

一、獲取Bean

第一階段獲取Bean

這里的流程圖的入口在 AbstractBeanFactory類的 doGetBean方法,這里可以配合前面的 getBean方法分析文章進(jìn)行閱讀。主要流程就是

1、先處理Bean 的名稱,因?yàn)槿绻浴?amp;”開(kāi)頭的Bean名稱表示獲取的是對(duì)應(yīng)的FactoryBean對(duì)象;
2、從緩存中獲取單例Bean,有則進(jìn)一步判斷這個(gè)Bean是不是在創(chuàng)建中,如果是的就等待創(chuàng)建完畢,否則直接返回這個(gè)Bean對(duì)象
3、如果不存在單例Bean緩存,則先進(jìn)行循環(huán)依賴的解析
4、解析完畢之后先獲取父類BeanFactory,獲取到了則調(diào)用父類的getBean方法,不存在則先合并然后創(chuàng)建Bean

二、創(chuàng)建Bean

2.1 創(chuàng)建Bean之前

在真正創(chuàng)建Bean之前邏輯

這個(gè)流程圖對(duì)應(yīng)的代碼在 AbstractAutowireCapableBeanFactory類的 createBean方法中。

1、這里會(huì)先獲取 RootBeanDefinition對(duì)象中的Class對(duì)象并確保已經(jīng)關(guān)聯(lián)了要?jiǎng)?chuàng)建的Bean的Class 。
2、這里會(huì)檢查3個(gè)條件

(1)Bean的屬性中的 beforeInstantiationResolved字段是否為true,默認(rèn)是false。
(2)Bean是原生的Bean
(3)Bean的 hasInstantiationAwareBeanPostProcessors屬性為true,這個(gè)屬性在Spring準(zhǔn)備刷新容器錢(qián)轉(zhuǎn)杯BeanPostProcessors的時(shí)候會(huì)設(shè)置,如果當(dāng)前Bean實(shí)現(xiàn)了 InstantiationAwareBeanPostProcessor則這個(gè)就會(huì)是true。

當(dāng)三個(gè)條件都存在的時(shí)候,就會(huì)調(diào)用實(shí)現(xiàn)的 InstantiationAwareBeanPostProcessor接口的 postProcessBeforeInstantiation方法,然后獲取返回的Bean,如果返回的Bean不是null還會(huì)調(diào)用實(shí)現(xiàn)的 BeanPostProcessor接口的 postProcessAfterInitialization方法,這里用代碼說(shuō)明

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;//條件1if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {//條件2跟條件3if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {//調(diào)用實(shí)現(xiàn)的postProcessBeforeInstantiation方法bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) { //調(diào)用實(shí)現(xiàn)的postProcessAfterInitialization方法bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}//不滿足2或者3的時(shí)候就會(huì)設(shè)置為falsembd.beforeInstantiationResolved = (bean != null);}return bean;}

3、如果上面3個(gè)條件其中一個(gè)不滿足就不會(huì)調(diào)用實(shí)現(xiàn)的方法。默認(rèn)這里都不會(huì)調(diào)用的這些 BeanPostProcessors的實(shí)現(xiàn)方法。然后繼續(xù)執(zhí)行后面的 doCreateBean方法。

2.1 真正的創(chuàng)建Bean,doCreateBean

doCreateBean方法邏輯

這個(gè)代碼的實(shí)現(xiàn)還是在 AbstractAutowireCapableBeanFactory方法中。流程是

1、先檢查 instanceWrapper變量是不是null,這里一般是null,除非當(dāng)前正在創(chuàng)建的Bean在 factoryBeanInstanceCache中存在這個(gè)是保存還沒(méi)創(chuàng)建完成的FactoryBean的集合。
2、調(diào)用createBeanInstance方法實(shí)例化Bean,這個(gè)方法在后面會(huì)講解
3、如果當(dāng)前 RootBeanDefinition對(duì)象還沒(méi)有調(diào)用過(guò)實(shí)現(xiàn)了的 MergedBeanDefinitionPostProcessor接口的方法,則會(huì)進(jìn)行調(diào)用 。
4、 當(dāng)滿足以下三點(diǎn)
(1)是單例Bean
(2)嘗試解析bean之間的循環(huán)引用
(3)bean目前正在創(chuàng)建中
則會(huì)進(jìn)一步檢查是否實(shí)現(xiàn)了 SmartInstantiationAwareBeanPostProcessor接口如果實(shí)現(xiàn)了則調(diào)用是實(shí)現(xiàn)的 getEarlyBeanReference方法 5、 調(diào)用 populateBean方法進(jìn)行屬性填充,這里后面會(huì)講解 6、 調(diào)用 initializeBean方法對(duì)Bean進(jìn)行初始化,這里后面會(huì)講解

2.1.1 實(shí)例化Bean,createBeanInstance

實(shí)例化Bean

這里的邏輯稍微有一點(diǎn)復(fù)雜,這個(gè)流程圖已經(jīng)是簡(jiǎn)化過(guò)后的了。簡(jiǎn)要根據(jù)代碼說(shuō)明一下流程

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {//步驟1Class<?> beanClass = resolveBeanClass(mbd, beanName);if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}//步驟2Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}//步驟3if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}boolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}//步驟4.1if (resolved) {if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);}else {return instantiateBean(beanName, mbd);}}//步驟4.2Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}//步驟5ctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}return instantiateBean(beanName, mbd);}

1、先檢查Class是否已經(jīng)關(guān)聯(lián)了,并且對(duì)應(yīng)的修飾符是否是public的
2、如果用戶定義了Bean實(shí)例化的函數(shù),則調(diào)用并返回
3、如果當(dāng)前Bean實(shí)現(xiàn)了 FactoryBean接口則調(diào)用對(duì)應(yīng)的 FactoryBean接口的 getObject方法
4、根據(jù)getBean時(shí)候是否傳入構(gòu)造參數(shù)進(jìn)行處理
4.1 如果沒(méi)有傳入構(gòu)造參數(shù),則檢查是否存在已經(jīng)緩存的無(wú)參構(gòu)造器,有則使用構(gòu)造器直接創(chuàng)建,沒(méi)有就會(huì)調(diào)用 instantiateBean方法先獲取實(shí)例化的策略默認(rèn)是 CglibSubclassingInstantiationStrategy,然后實(shí)例化Bean。最后返回
4.2 如果傳入了構(gòu)造參數(shù),則會(huì)先檢查是否實(shí)現(xiàn)了 SmartInstantiationAwareBeanPostProcessor接口,如果實(shí)現(xiàn)了會(huì)調(diào)用 determineCandidateConstructors獲取返回的候選構(gòu)造器。
4.3 檢查4個(gè)條件是否滿足一個(gè)
(1)構(gòu)造器不為null,
(2)從RootBeanDefinition中獲取到的關(guān)聯(lián)的注入方式是構(gòu)造器注入(沒(méi)有構(gòu)造參數(shù)就是setter注入,有則是構(gòu)造器注入)
(3)含有構(gòu)造參數(shù)
(4)getBean方法傳入構(gòu)造參數(shù)不是空

滿足其中一個(gè)則會(huì)調(diào)用返回的候選構(gòu)造器實(shí)例化Bean并返回,如果都不滿足,則會(huì)根據(jù)構(gòu)造參數(shù)選則合適的有參構(gòu)造器然后實(shí)例化Bean并返回

5、如果上面都沒(méi)有合適的構(gòu)造器,則直接使用無(wú)參構(gòu)造器創(chuàng)建并返回Bean。

2.1.2 填充Bean,populateBean

填充Bean

這里還是根據(jù)代碼來(lái)說(shuō)一下流程

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {if (bw == null) {if (mbd.hasPropertyValues()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");}else {// Skip property population phase for null instance.return;}}boolean continueWithPropertyPopulation = true;//步驟1if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}}if (!continueWithPropertyPopulation) {return;} //步驟2--------------------PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);int resolvedAutowireMode = mbd.getResolvedAutowireMode();if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null; //步驟3if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}}if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}checkDependencies(beanName, mbd, filteredPds, pvs);} //步驟4if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}}

1、檢查當(dāng)前Bean是否實(shí)現(xiàn)了 InstantiationAwareBeanPostProcessor的 postProcessAfterInstantiation方法則調(diào)用,并結(jié)束B(niǎo)ean的填充。
2、將按照類型跟按照名稱注入的Bean分開(kāi),如果注入的Bean還沒(méi)有實(shí)例化的這里會(huì)實(shí)例化,然后放到 PropertyValues對(duì)象中。
3、如果實(shí)現(xiàn)了 InstantiationAwareBeanPostProcessor類的 postProcessProperties則調(diào)用這個(gè)方法并獲取返回值,如果返回值是null,則有可能是實(shí)現(xiàn)了過(guò)期的 postProcessPropertyValues方法,這里需要進(jìn)一步調(diào)用 postProcessPropertyValues方法
4、進(jìn)行參數(shù)填充

2.1.3 初始化Bean,initializeBean

初始化Bean

同時(shí)這里根據(jù)代碼跟流程圖來(lái)說(shuō)明

1、如果Bean實(shí)現(xiàn)了 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware則調(diào)用對(duì)應(yīng)實(shí)現(xiàn)的方法 。
2、Bean不為null并且bean不是合成的,如果實(shí)現(xiàn)了 BeanPostProcessor的 postProcessBeforeInitialization則會(huì)調(diào)用實(shí)現(xiàn)的 postProcessBeforeInitialization方法。在 ApplicationContextAwareProcessor類中實(shí)現(xiàn)了 postProcessBeforeInitialization方法。而這個(gè)類會(huì)在Spring刷新容器準(zhǔn)備 beanFactory的時(shí)候會(huì)加進(jìn)去,這里就會(huì)被調(diào)用,而調(diào)用里面會(huì)檢查Bean是不是 EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware的實(shí)現(xiàn)類。這里就會(huì)調(diào)用對(duì)應(yīng)的實(shí)現(xiàn)方法。代碼如下

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {.......beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));....... public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){return bean;}AccessControlContext acc = null;if (System.getSecurityManager() != null) {acc = this.applicationContext.getBeanFactory().getAccessControlContext();}if (acc != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareInterfaces(bean);return null;}, acc);}else {invokeAwareInterfaces(bean);}return bean;}

1、實(shí)例化Bean然后,檢查是否實(shí)現(xiàn)了 InitializingBean的 afterPropertiesSet方法,如果實(shí)現(xiàn)了就會(huì)調(diào)用
2、Bean不為null并且bean不是合成的,如果實(shí)現(xiàn)了 BeanPostProcessor的 postProcessBeforeInitialization則會(huì)調(diào)用實(shí)現(xiàn)的 postProcessAfterInitialization方法。

到此創(chuàng)建Bean 的流程就沒(méi)了,剩下的就是容器銷毀的時(shí)候的了

三、destory方法跟銷毀Bean

Bean在創(chuàng)建完畢之后會(huì)檢查用戶是否指定了 destroyMethodName以及是否實(shí)現(xiàn)了 DestructionAwareBeanPostProcessor接口的 requiresDestruction方法,如果指定了會(huì)記錄下來(lái)保存在 DisposableBeanAdapter對(duì)象中并保存在bean的 disposableBeans屬性中。代碼在 AbstractBeanFactory的 registerDisposableBeanIfNecessary中

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {......registerDisposableBean(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));......}public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {.......String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {......this.destroyMethod = destroyMethod;}this.beanPostProcessors = filterPostProcessors(postProcessors, bean);}

在銷毀Bean的時(shí)候最后都會(huì)調(diào)用 AbstractAutowireCapableBeanFactory的 destroyBean方法。

public void destroyBean(Object existingBean) {new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy();}

這里是創(chuàng)建一個(gè) DisposableBeanAdapter對(duì)象,這個(gè)對(duì)象實(shí)現(xiàn)了Runnable接口,在實(shí)現(xiàn)的 run方法中會(huì)調(diào)用實(shí)現(xiàn)的 DisposableBean接口的 destroy方法。并且在創(chuàng)建 DisposableBeanAdapter對(duì)象的時(shí)候會(huì)根據(jù)傳入的bean是否實(shí)現(xiàn)了 DisposableBean接口來(lái)設(shè)置 invokeDisposableBean變量,這個(gè)變量表實(shí)有沒(méi)有實(shí)現(xiàn) DisposableBean接口

public DisposableBeanAdapter(Object bean, List<BeanPostProcessor> postProcessors, AccessControlContext acc) {Assert.notNull(bean, "Disposable bean must not be null");this.bean = bean;this.beanName = bean.getClass().getName();//根據(jù)傳入的bean是否實(shí)現(xiàn)了`DisposableBean`接口來(lái)設(shè)置`invokeDisposableBean`變量this.invokeDisposableBean = (this.bean instanceof DisposableBean);this.nonPublicAccessAllowed = true;this.acc = acc;this.beanPostProcessors = filterPostProcessors(postProcessors, bean);}public void destroy() {......//根據(jù)invokeDisposableBean決定是否調(diào)用destroy方法if (this.invokeDisposableBean) {if (logger.isTraceEnabled()) {logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");}try {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((DisposableBean) this.bean).destroy();return null;}, this.acc);}else {((DisposableBean) this.bean).destroy();}}catch (Throwable ex) {String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";if (logger.isDebugEnabled()) {logger.warn(msg, ex);}else {logger.warn(msg + ": " + ex);}}} ......}

四、總結(jié)

最后來(lái)一個(gè)大的流程

實(shí)例化前的準(zhǔn)備階段

實(shí)例化前

實(shí)例化后

初始化前

原創(chuàng)電子書(shū)

歷時(shí)整整一年總結(jié)的?Java 面試 + Java 后端技術(shù)學(xué)習(xí)指南,這是本人這幾年及校招的總結(jié),各種高頻面試題已經(jīng)全部進(jìn)行總結(jié),按照章節(jié)復(fù)習(xí)即可,已經(jīng)拿到了大廠offer。

原創(chuàng)思維導(dǎo)圖

掃碼或者微信搜?程序員的技術(shù)圈子?回復(fù)?面試?領(lǐng)取原創(chuàng)電子書(shū)和思維導(dǎo)圖。

總結(jié)

以上是生活随笔為你收集整理的11 张流程图帮你搞定 Spring Bean 生命周期 (核心)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。