1. 程式人生 > >Spring容器啟動流程+Bean的生命週期【附原始碼】

Spring容器啟動流程+Bean的生命週期【附原始碼】

如果對SpringIoc與Aop的原始碼感興趣,可以訪問參考:[https://javadoop.com/](https://javadoop.com/),十分詳細。 [toc] # Spring容器的啟動全流程 Spring容器的啟動流程如下,這是我在看原始碼過程中自己總結的流程圖,如有錯誤,還望評論區指點: ![](https://img2020.cnblogs.com/blog/1771072/202009/1771072-20200909164014978-2077560080.png) 接下來附上原始碼: > 為什麼是refresh方法命名,而不是init命名呢? > > 其實,在ApplicaitonContext建立起來之後,可以通過refresh進行重建,將原來的ac銷燬,重新執行一次初始化操作,用refresh更加貼切。 ```java public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { //如果已經有application Context ,並需要配置成父子關係, 呼叫該構造方法 super(parent); // 根據提供的路徑,處理成配置檔案陣列(以分號、逗號、空格、tab、換行符分割) setConfigLocations(configLocations); if (refresh) { refresh();//核心!!! } } ``` 雖然`ApplicationContext`繼承自`BeanFactory`,更確切地說是`ApplicationContext`內部持有了一個例項化的`BeanFactory(DefaultListableBeanFactory)`,`BeanFactory`的相關操作其實是委託給這個例項來處理。 ```java @Override public void refresh() throws BeansException, IllegalStateException { //保證容器啟動銷燬操作的併發安全 synchronized (this.startupShutdownMonitor) { //準備工作, 記錄容器的啟動時間, 標記已啟動狀態, 處理配置檔案種的佔位符 prepareRefresh(); //這步用於將配置檔案解析成一個個bean definition,註冊到重建的beanFactory中,(只是提取了配置資訊,bean並沒有初始化),同時還設定兩個配置屬性:1、是否允許bean覆蓋2、是否允許迴圈引用 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //設定beanFactory的類載入器, 新增幾個beanPostProcessor ,手動註冊幾個特殊的bean prepareBeanFactory(beanFactory); try { //如果bean實現了beanFactoryPostProcessor 將會執行postProcessBeanFactory方法 提供子類的擴充套件點,到這bean都載入、註冊完成,但沒有初始化,具體的子類可以在這步新增特殊bfpp實現類做事 postProcessBeanFactory(beanFactory); //呼叫bfpp的各個實現類的ppbf方法 invokeBeanFactoryPostProcessors(beanFactory); //註冊BeanPostProcessor的實現類,BeanPostProcessor將在bean初始化前後執行 registerBeanPostProcessors(beanFactory); //初始化當前 ApplicationContext 的 MessageSource,國際化 initMessageSource(); //初始化當前 ApplicationContext 的事件廣播器 initApplicationEventMulticaster(); //模板方法(鉤子方法,具體的子類可以在這裡初始化一些特殊的 Bean(在初始化 singleton beans 之前) onRefresh(); //註冊事件監聽器,監聽器需要實現 ApplicationListener 介面。 registerListeners(); //例項化+初始化所有的非懶載入的單例bean finishBeanFactoryInitialization(beanFactory); //廣播事件,ApplicationContext 初始化完成 finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources.銷燬已經初始化的 singleton 的 Beans,以免有些 bean 會一直佔用資源 destroyBeans(); cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { resetCommonCaches(); } } } ``` 利用註解方式大致也是按照這個流程一步步下來,不同在於,AnnotationConfigApplicationContext在執行構造器的時候,已經通過`scan(basePackages);`將beanDefination讀取到。 > 將bean的定義轉化為BeanDefination: 如果利用AnnotationConfigApplicationContext。 ```java public AnnotationConfigApplicationContext(String... basePackages) { this(); scan(basePackages);//這個過程中配置已經被轉化為一個個的beanDefinition refresh(); } ``` # Spring容器關閉流程 ```java protected void doClose() { if (this.active.get() && this.closed.compareAndSet(false, true)) { if (logger.isDebugEnabled()) { logger.debug("Closing " + this); } //取消註冊上下文 if (!IN_NATIVE_IMAGE) { LiveBeansView.unregisterApplicationContext(this); } // 釋出事件 publishEvent(new ContextClosedEvent(this)); // 停止所有Lifecycle bean,以避免在銷燬期間造成延遲。 if (this.lifecycleProcessor != null) { this.lifecycleProcessor.onClose(); } // 銷燬上下文的BeanFactory中所有快取的單例。 destroyBeans(); // 關閉此上下文字身的狀態。 closeBeanFactory(); // 讓子類善後 onClose(); // 充值本地應用堅硬其為pre-refresh狀態 if (this.earlyApplicationListeners != null) { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // 切換為非活動狀態 this.active.set(false); } } ``` 大概就是:先發布事件,再摧毀Factory中的bean,再摧毀Factory本身,最後設定一些狀態。 而Bean週期中的銷燬部分就存在於`destroyBeans`中。當然,銷燬bean也是需要先銷燬它所依賴的bean。 # Bean 的生命週期 ![](https://img2020.cnblogs.com/blog/1771072/202009/1771072-20200909164026351-1683760583.png) 在瞭解Bean的生命週期之前,我們必須要明確SpringBean和我們通常說的物件有什麼區別? > SpringBean是**由SpringIoC容器管理**的,是一個**被例項化,組裝,並通過容器管理的物件**,可通過getBean()獲取。**容器通過讀取配置的元資料,解析成BeanDefinition,註冊到BeanFactory中,加入到singletonObjects快取池中**。 ## Bean的建立 在上面的流程中,只有到`finishBeanFactoryInitialization(beanFactory);`這一步,才開始對非懶載入例項的例項化+ 初始化。 ```java //例項化所有剩餘的非懶載入的單例bean beanFactory.preInstantiateSingletons(); ``` 可以看一下這一步的具體實現:DefaultListableBeanFactory ```java public void preInstantiateSingletons() throws BeansException { //擁有所有的beanNames List beanNames = new ArrayList<>(this.beanDefinitionNames); // 觸發所有非懶載入的singleton beans的例項化+初始化操作 for (String beanName : beanNames) { //對bean繼承的處理,合併父bean 中的配置 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //非抽象,非懶載入的singletons if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //處理factoryBean if (isFactoryBean(beanName)) { //如果是factoryBean,在beanName錢加上&,再呼叫getBean方法 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { FactoryBean factory = (FactoryBean) bean; boolean isEagerInit; //判斷當前 FactoryBean 是否是 SmartFactoryBean 的實現 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { getBean(beanName);//普通的bean,直接呼叫getBean進行例項化 } } } } ``` 只有`!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()`條件滿足的時候,這一步才會進行例項化,另外,Spring還對其是否為FactoryBean進行判斷,當然了,一般來說,最最普通的bean都會在最後一個else分支中進行例項化。 ### doGetBean全流程 這部分篇幅過長,我直接放上總結的流程圖: ![](https://img2020.cnblogs.com/blog/1771072/202009/1771072-20200909164033489-801923330.png) ### createBean 那麼createBean又幹了什麼事呢,稍微看看就可以: ```java //省略許多異常處理的部分 @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {//初始化階段的args == null RootBeanDefinition mbdToUse = mbd; // 確保 BeanDefinition 中的 Class 被載入 Class resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // 準備方法覆寫它來自於 bean 定義中的
mbdToUse.prepareMethodOverrides(); // 讓 InstantiationAwareBeanPostProcessor 在這一步有機會返回代理 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; // 重頭戲,建立 bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance; } ``` 我們的重點放在`Object beanInstance = doCreateBean(beanName, mbdToUse, args);`這一步上,我們已經知道,Bean的例項化+初始化都在這一步中完成。 ### doCreateBean 在這個doCreateBean方法中,存在三個重要方法: #### createBeanInstance 建立例項 ```java protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { //確保已經載入了這個class Class beanClass = resolveBeanClass(mbd, beanName); //校驗這個類的訪問許可權 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(); } //spring5.0 返回建立bean例項的回撥 Supplier instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } if (mbd.getFactoryMethodName() != null) { //採用工廠方法例項化 return instantiateUsingFactoryMethod(beanName, mbd, args); } // 如果是第二次建立 如prototype bean,這種情況下,我們可以從第一次建立知道,採用無參建構函式,還是建構函式依賴注入 來完成例項化 boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { //建構函式注入 return autowireConstructor(beanName, mbd, null, null); } else { //無參建構函式 return instantiateBean(beanName, mbd); } } // 判斷是否採用有參建構函式 Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { //args!=null 的建構函式注入(有參) return autowireConstructor(beanName, mbd, ctors, args); } // Preferred constructors for default construction? ctors = mbd.getPreferredConstructors(); if (ctors != null) { //判斷是否採用首選的建構函式 return autowireConstructor(beanName, mbd, ctors, null); } // 呼叫無參建構函式 return instantiateBean(beanName, mbd); } ``` 以無參建構函式為例,例項化的過程在SimpleInstantiationStrategy中。 - 如果不存在方法重寫:可以直接使用Java的反射進行例項化。 - 否則使用CGLIB實現例項化。 ```java public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // 如果不存在方法覆寫,就是用java的反射進行例項化, 否則使用CGLIB if (!bd.hasMethodOverrides()) { Constructor constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction>) clazz::getDeclaredConstructor); } else { constructorToUse = clazz.getDeclaredConstructor(); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } //利用構造方法進行例項化 return BeanUtils.instantiateClass(constructorToUse); } else { // 存在方法覆寫的情況,需要利用CGLIB來完成例項化,需要依賴於CGLIB生成子類 return instantiateWithMethodInjection(bd, beanName, owner); } } ``` 此時,Bean例項已經通過構造方法或者工廠方法建立,但是其中的屬性,如依賴注入的各種屬性尚未填充。 #### populateBean 填充屬性 ```java protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) {//this.propertyValues bean例項的所有屬性 throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } //在設定屬性之前,給所有InstantiationAwareBeanPostProcessor機會修改bean的狀態 // 【此時bean的狀態 = 已經通過工廠方法或者構造方法例項化,在屬性賦值之前】。例如,可以使用支援欄位注入的樣式。InstantiationAwareBeanPostProcessor if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);//獲取PropertyValue物件 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {//獲取Autowire的模式 or 通過名字, or 通過型別 MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 通過名字找到所有屬性值,如果是 bean 依賴,先初始化依賴的 bean。記錄依賴關係 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 通過型別裝配 記錄依賴關係 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } //...省略 //設定bean例項的屬性值 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } } ``` #### initializeBean 回撥方法 屬性注入完成,處理各種回撥,如BeanNameAware、BeanClassLoaderAware、BeanFactoryAware等。 ```java protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {// if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean);//如果bean實現了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware介面, 回撥 } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//BeanPostProcessor 的 postProcessBeforeInitialization 回撥 } try { invokeInitMethods(beanName, wrappedBean, mbd);//處理bean中定義的init-method或 bean實現了InitializingBean ,呼叫afterPropertiesSet() 方法 } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//BeanPostProcessor 的 postProcessAfterInitialization 回撥 } return wrappedBean; } ``` ## Bean的銷燬 DisposableBeanAdapter.java ```java @Override public void destroy() { //CommonAnnotationBeanPostProcessorc 處理@preDetroy if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { processor.postProcessBeforeDestruction(this.bean, this.beanName); } } if (this.invokeDisposableBean) {////DisposableBean的destroy方法 ((DisposableBean) this.bean).destroy(); } } if (this.destroyMethod != null) {//destroy-method方法 invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName != null) { Method methodToInvoke = determineDestroyMethod(this.destroyMethodName); if (methodToInvoke != null) { invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); } } } ``` > 參考資料: > - [https://javadoop.com/post/spring-ioc](https://javadoop.com/post/spring-ioc) > - [https://www.cnblogs.com/mpyn/p/12134041.html](https://www.cnblogs.com/mpyn/p/12134041.html) > - [https://www.cnblogs.com/binghe001/p/13174687.html](https://www.cnblogs.com/binghe001/p/131746