javascript
11 张流程图帮你搞定 Spring Bean 生命周期 (核心)
點擊上方?好好學java?,選擇?星標?公眾號
重磅資訊、干貨,第一時間送達
今日推薦:騰訊推出高性能 RPC 開發框架
個人原創100W+訪問量博客:點擊前往,查看更多
來源:www.jianshu.com/p/70b935f2b3fe
在網上已經有跟多Bean的生命周期的博客,但是很多都是基于比較老的版本了,最近把整個流程化成了一個流程圖。待會兒使用流程圖,說明以及代碼的形式來說明整個聲明周期的流程。注意因為代碼比較多,這里的流程圖只畫出了大概的流程,具體的可以深入代碼。
一、獲取Bean
第一階段獲取Bean
這里的流程圖的入口在 AbstractBeanFactory類的 doGetBean方法,這里可以配合前面的 getBean方法分析文章進行閱讀。主要流程就是
1、先處理Bean 的名稱,因為如果以“&”開頭的Bean名稱表示獲取的是對應的FactoryBean對象;
2、從緩存中獲取單例Bean,有則進一步判斷這個Bean是不是在創建中,如果是的就等待創建完畢,否則直接返回這個Bean對象
3、如果不存在單例Bean緩存,則先進行循環依賴的解析
4、解析完畢之后先獲取父類BeanFactory,獲取到了則調用父類的getBean方法,不存在則先合并然后創建Bean
二、創建Bean
2.1 創建Bean之前
在真正創建Bean之前邏輯
這個流程圖對應的代碼在 AbstractAutowireCapableBeanFactory類的 createBean方法中。
1、這里會先獲取 RootBeanDefinition對象中的Class對象并確保已經關聯了要創建的Bean的Class 。
2、這里會檢查3個條件
(1)Bean的屬性中的 beforeInstantiationResolved字段是否為true,默認是false。
(2)Bean是原生的Bean
(3)Bean的 hasInstantiationAwareBeanPostProcessors屬性為true,這個屬性在Spring準備刷新容器錢轉杯BeanPostProcessors的時候會設置,如果當前Bean實現了 InstantiationAwareBeanPostProcessor則這個就會是true。
當三個條件都存在的時候,就會調用實現的 InstantiationAwareBeanPostProcessor接口的 postProcessBeforeInstantiation方法,然后獲取返回的Bean,如果返回的Bean不是null還會調用實現的 BeanPostProcessor接口的 postProcessAfterInitialization方法,這里用代碼說明
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) {//調用實現的postProcessBeforeInstantiation方法bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) { //調用實現的postProcessAfterInitialization方法bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}//不滿足2或者3的時候就會設置為falsembd.beforeInstantiationResolved = (bean != null);}return bean;}3、如果上面3個條件其中一個不滿足就不會調用實現的方法。默認這里都不會調用的這些 BeanPostProcessors的實現方法。然后繼續執行后面的 doCreateBean方法。
2.1 真正的創建Bean,doCreateBean
doCreateBean方法邏輯
這個代碼的實現還是在 AbstractAutowireCapableBeanFactory方法中。流程是
1、先檢查 instanceWrapper變量是不是null,這里一般是null,除非當前正在創建的Bean在 factoryBeanInstanceCache中存在這個是保存還沒創建完成的FactoryBean的集合。
2、調用createBeanInstance方法實例化Bean,這個方法在后面會講解
3、如果當前 RootBeanDefinition對象還沒有調用過實現了的 MergedBeanDefinitionPostProcessor接口的方法,則會進行調用 。
4、 當滿足以下三點
(1)是單例Bean
(2)嘗試解析bean之間的循環引用
(3)bean目前正在創建中
則會進一步檢查是否實現了 SmartInstantiationAwareBeanPostProcessor接口如果實現了則調用是實現的 getEarlyBeanReference方法 5、 調用 populateBean方法進行屬性填充,這里后面會講解 6、 調用 initializeBean方法對Bean進行初始化,這里后面會講解
2.1.1 實例化Bean,createBeanInstance
實例化Bean
這里的邏輯稍微有一點復雜,這個流程圖已經是簡化過后的了。簡要根據代碼說明一下流程
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是否已經關聯了,并且對應的修飾符是否是public的
2、如果用戶定義了Bean實例化的函數,則調用并返回
3、如果當前Bean實現了 FactoryBean接口則調用對應的 FactoryBean接口的 getObject方法
4、根據getBean時候是否傳入構造參數進行處理
4.1 如果沒有傳入構造參數,則檢查是否存在已經緩存的無參構造器,有則使用構造器直接創建,沒有就會調用 instantiateBean方法先獲取實例化的策略默認是 CglibSubclassingInstantiationStrategy,然后實例化Bean。最后返回
4.2 如果傳入了構造參數,則會先檢查是否實現了 SmartInstantiationAwareBeanPostProcessor接口,如果實現了會調用 determineCandidateConstructors獲取返回的候選構造器。
4.3 檢查4個條件是否滿足一個
(1)構造器不為null,
(2)從RootBeanDefinition中獲取到的關聯的注入方式是構造器注入(沒有構造參數就是setter注入,有則是構造器注入)
(3)含有構造參數
(4)getBean方法傳入構造參數不是空
滿足其中一個則會調用返回的候選構造器實例化Bean并返回,如果都不滿足,則會根據構造參數選則合適的有參構造器然后實例化Bean并返回
5、如果上面都沒有合適的構造器,則直接使用無參構造器創建并返回Bean。
2.1.2 填充Bean,populateBean
填充Bean
這里還是根據代碼來說一下流程
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、檢查當前Bean是否實現了 InstantiationAwareBeanPostProcessor的 postProcessAfterInstantiation方法則調用,并結束Bean的填充。
2、將按照類型跟按照名稱注入的Bean分開,如果注入的Bean還沒有實例化的這里會實例化,然后放到 PropertyValues對象中。
3、如果實現了 InstantiationAwareBeanPostProcessor類的 postProcessProperties則調用這個方法并獲取返回值,如果返回值是null,則有可能是實現了過期的 postProcessPropertyValues方法,這里需要進一步調用 postProcessPropertyValues方法
4、進行參數填充
2.1.3 初始化Bean,initializeBean
初始化Bean
同時這里根據代碼跟流程圖來說明
1、如果Bean實現了 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware則調用對應實現的方法 。
2、Bean不為null并且bean不是合成的,如果實現了 BeanPostProcessor的 postProcessBeforeInitialization則會調用實現的 postProcessBeforeInitialization方法。在 ApplicationContextAwareProcessor類中實現了 postProcessBeforeInitialization方法。而這個類會在Spring刷新容器準備 beanFactory的時候會加進去,這里就會被調用,而調用里面會檢查Bean是不是 EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware的實現類。這里就會調用對應的實現方法。代碼如下
1、實例化Bean然后,檢查是否實現了 InitializingBean的 afterPropertiesSet方法,如果實現了就會調用
2、Bean不為null并且bean不是合成的,如果實現了 BeanPostProcessor的 postProcessBeforeInitialization則會調用實現的 postProcessAfterInitialization方法。
到此創建Bean 的流程就沒了,剩下的就是容器銷毀的時候的了
三、destory方法跟銷毀Bean
Bean在創建完畢之后會檢查用戶是否指定了 destroyMethodName以及是否實現了 DestructionAwareBeanPostProcessor接口的 requiresDestruction方法,如果指定了會記錄下來保存在 DisposableBeanAdapter對象中并保存在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的時候最后都會調用 AbstractAutowireCapableBeanFactory的 destroyBean方法。
public void destroyBean(Object existingBean) {new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy();}這里是創建一個 DisposableBeanAdapter對象,這個對象實現了Runnable接口,在實現的 run方法中會調用實現的 DisposableBean接口的 destroy方法。并且在創建 DisposableBeanAdapter對象的時候會根據傳入的bean是否實現了 DisposableBean接口來設置 invokeDisposableBean變量,這個變量表實有沒有實現 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();//根據傳入的bean是否實現了`DisposableBean`接口來設置`invokeDisposableBean`變量this.invokeDisposableBean = (this.bean instanceof DisposableBean);this.nonPublicAccessAllowed = true;this.acc = acc;this.beanPostProcessors = filterPostProcessors(postProcessors, bean);}public void destroy() {......//根據invokeDisposableBean決定是否調用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);}}} ......}四、總結
最后來一個大的流程
實例化前的準備階段
實例化前
實例化后
初始化前
原創電子書
歷時整整一年總結的?Java 面試 + Java 后端技術學習指南,這是本人這幾年及校招的總結,各種高頻面試題已經全部進行總結,按照章節復習即可,已經拿到了大廠offer。
原創思維導圖
掃碼或者微信搜?程序員的技術圈子?回復?面試?領取原創電子書和思維導圖。
總結
以上是生活随笔為你收集整理的11 张流程图帮你搞定 Spring Bean 生命周期 (核心)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 今年的校招,Java好拿offer吗?
- 下一篇: 给新手的 11 个 Docker 免费上