spring bean初始化順序

spring使用BeanFactory來實例化、配置和管理對象,可是它只是一個接口,裏面有一個getBean()方法。咱們通常都不直接用BeanFactory,而是用它的實現類ApplicationContext,這個類會自動解析咱們配置的applicationContext.xml,而後根據咱們配置的bean來new對象,將new好的對象放進一個Map中,鍵就是咱們bean的id,值就是new的對象。java

經常使用的設定方式有如下三種:spring

  1. 經過實現 InitializingBean/DisposableBean 接口來定製初始化以後/銷燬以前的操做方法;
  2. 經過 <bean> 元素的 init-method/destroy-method屬性指定初始化以後 /銷燬以前調用的操做方法;
  3. 在指定方法上加上@PostConstruct 或@PreDestroy註解來制定該方法是在初始化以後仍是銷燬以前調用。  
public class InitSequenceBean implements InitializingBean {    
     
    public InitSequenceBean() {    
       System.out.println("InitSequenceBean: constructor");    
    }    
       
    @PostConstruct    
    public void postConstruct() {    
       System.out.println("InitSequenceBean: postConstruct");    
    }    
       
    public void initMethod() {    
       System.out.println("InitSequenceBean: init-method");    
    }    
       
    @Override    
    public void afterPropertiesSet() throws Exception {    
       System.out.println("InitSequenceBean: afterPropertiesSet");    
    }    
}

而且在配置文件中添加以下Bean定義:app

<bean class="InitSequenceBean" init-method="initMethod"></bean>

輸出結果:ide

InitSequenceBean: constructor
InitSequenceBean: postConstruct
InitSequenceBean: afterPropertiesSet
InitSequenceBean: init-method

經過上述輸出結果,說明三種初始化的順序是:
Constructor > @PostConstruct > InitializingBean > init-methodpost

緣由:
@PostConstruct註解後的方法在BeanPostProcessor前置處理器中就被執行了。咱們知道BeanPostProcessor接口是一個回調的做用,spring容器的每一個受管Bean在調用初始化方法以前,都會得到BeanPostProcessor接口實現類的一個回調。在BeanPostProcessor的方法中有一段邏輯就是會判斷當前被回調的bean的方法中有沒有被initAnnotationType/destroyAnnotationType註釋,若是有,則添加到init/destroy隊列中,後續一一執行。initAnnotationType/destroyAnnotationType註解就是@PostConstruct/@PreDestroy。因此@PostConstruct固然要先於InitializingBean和init-method執行了。prototype

從圖中,咱們能夠看到實例化Bean的過程當中有如下幾個節點:code

  1. 設置屬性值;
  2. 調用Bean中的BeanNameAware.setBeanName()方法,若是該Bean實現了BeanNameAware接口;
  3. 調用Bean中的BeanFactoryAware.setBeanFactory()方法,若是該Bean實現了BeanFactoryAware接口;
  4. 調用BeanPostProcessors.postProcessBeforeInitialization()方法;@PostConstruct註解後的方法就是在這裏被執行的
  5. 調用Bean中的afterPropertiesSet方法,若是該Bean實現了InitializingBean接口;
  6. 調用Bean中的init-method,一般是在配置bean的時候指定了init-method,例如:<bean class="beanClass" init-method="init"></bean>
  7. 調用BeanPostProcessors.postProcessAfterInitialization()方法;@PreDestroy註解後的方法就是在這裏被執行的
  8. 若是該Bean是單例的,則當容器銷燬而且該Bean實現了DisposableBean接口的時候,調用destory方法;若是該Bean是prototype,則將準備好的Bean提交給調用者,後續再也不管理該Bean的生命週期。
相關文章
相關標籤/搜索