Java面試題:淺談Spring Bean的生命周期


摘要:如果熟悉Spring 中 Bean的生命周期,可以加深對Spring的認知,故綜述一下Bean的生命周期。

前言

  Spring中Bean的生命周期是找工作的時候會被問到的高頻面試題,主要用於考察應聘者對Spring是否熟悉,工作中很少用到其中的內容。

  配置在Spring中的Bean在Spring容器中從加載到銷毀會經歷哪些過程呢?如果實現一些特定的Spring接口,這些特定接口的方法會在什么時候被調用呢?

  Bean初始化入口:以Spring Boot項目為例,在項目啟動的時候,SpringApplication的run方法會調用函數refreshContext(ApplicationContext applicationContext),此函數最終調用 AbstractApplicationContext 類的refresh()方法以刷新容器,創建Bean。refresh()方法源碼如下,如果為了面試,可以跳過(嘻嘻):


	/** Synchronization monitor for the "refresh" and "destroy". */
	private final Object startupShutdownMonitor = new Object();
	 @Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
 
            // 設置Spring容器的啟動時間,撤銷關閉狀態,開啟活躍狀態
            // Prepare this context for refreshing.
			prepareRefresh(); 
            // 得到BeanFactory
            // Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 
            // 給BeanFactory設置一些屬性
            // Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory); 
			try { 
                // 后置處理BeanFactory
				postProcessBeanFactory(beanFactory); 
                // 注冊並調用BeanFactoryPostProcessor后置處理器
                // 其中ConfigurationClassPostProcessor這個后置處理器會掃描Bean並且注冊到容器中
//這個方法做了很多事,Spring IOC容器初始化中的資源定位、BeanDefinition載入和解析、BeanDefinition注冊都是這個方法完成的
				invokeBeanFactoryPostProcessors(beanFactory); 
                // 注冊BeanPostProcessor后置處理器,這里的后置處理器在下方實例化Bean方法中會用到
				registerBeanPostProcessors(beanFactory); 
				initMessageSource();
 
                // 初始化ApplicationEventMulticaster
				initApplicationEventMulticaster(); 
                //創建tomcat啟動了Tomcat的Server、Service、Container、Engine、Realm、Pipeline、Value、MapperListerner
                onRefresh(); 
                // 注冊監聽器
				registerListeners(); 
                // 實例化非懶加載的Bean
				finishBeanFactoryInitialization(beanFactory); 
                // 啟動tomcat的Connector
				finishRefresh();
			} catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +	 "cancelling refresh attempt: " + ex);
				}
 
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans(); 
				// Reset 'active' flag.
				cancelRefresh(ex); 
				// Propagate exception to caller.
				throw ex;
			} finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

Bean的生命周期

  一個Bean從創建到銷毀,如果是用BeanFactory來生成和管理Bean的話,主要會經歷四個過程:實例化 -> 屬性賦值 -> 初始化 -> 銷毀。

  • 實例化 Instantiation
  • 屬性賦值 Populate
  • 初始化 Initialization
  • 銷毀 Destruction

  spring Bean加載的過程主要就是執行AbstractApplicationContext類中的refresh方法。完整生命周期如下圖所示:

  1. Bean實例化
    也就是我們常說的new,調用Bean的構造函數或者工廠方法。

  2. 屬性賦值
    對Bean的成員變量賦值。使用依賴注入,Spring按照Bean定義信息配置Bean所有屬性。

  3. BeanNameAware的setBeanName()
    如果Bean類有實現org.springframework.beans.BeanNameAware接口,工廠調用Bean的setBeanName()方法傳遞Bean的ID。

  4. BeanFactoryAware的setBeanFactory()
    如果Bean類有實現org.springframework.beans.factory.BeanFactoryAware接口,工廠調用setBeanFactory()方法傳入工廠自身。

  5. 實現了ApplicationContextAware接口
    使用ApplicationContext來生成並管理Bean的話,才有此步;否則,沒有。
    如果這個Bean已經實現了ApplicationContextAware接口,會調用setApplicationContext(ApplicationContext)方法,傳入Spring上下文(同樣這個方式也可以實現上一步的內容,但比上一步更好,因為ApplicationContext是BeanFactory的子接口,有更多的實現方法);

  6. BeanPostProcessors的ProcessBeforeInitialization()
    如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean關聯,那么其postProcessBeforeInitialization()方法將被將被調用。

  7. initializingBean的afterPropertiesSet():
    如果Bean類已實現org.springframework.beans.factory.InitializingBean接口,則執行他的afterProPertiesSet()方法。

  8. Bean定義文件中定義init-method
    如果在Bean定義文件中使用“init-method”屬性設定方法名稱,如下:
    <bean id="demoBean" class="com.yangsq.bean.DemoBean" init-method="initMethod">
      .......
     </bean>
    則會執行initMethod()方法,注意,這個方法是不帶參數的。

  9. BeanPostProcessors的ProcessaAfterInitialization()
    容器中如果有實現org.springframework.beans.factory.BeanPostProcessors接口的實例,則Bean在初始化之前都會執行這個實例的processAfterInitialization()方法。

  10. Bean處於可以使用的狀態。
    此時,Bean已經可以被應用系統使用,並且將保留在BeanFactory中直到它不再被使用。

  11. Spring容器關閉。
    下面介紹銷毀流程。

  12. DisposableBean的destroy()
    容器關閉時,如果Bean類實現了org.springframework.beans.factory.DisposableBean接口,則執行它的destroy()方法。

  13. Bean定義文件中定義destroy-method
    在容器關閉時,可以在Bean定義文件中使用"destroy-method"屬性設定方法名稱。例如:
    <bean id="demoBean" class="com.yangsq.bean.DemoBean" destory-method="destroyMethod">
      .......
    </bean>
    這時會執行destroyMethod()方法,注意,這個方法是不帶參數的。

小結

  在Spring框架中,一旦把一個bean納入到Spring IoC容器之中,這個bean的生命周期就會交由容器進行管理,一般擔當管理者角色的是BeanFactory或ApplicationContext。認識一下Bean的生命周期活動,對更好的利用它有很大的幫助。

Reference


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM