Spring5源碼分析之Bean生命週期

Spring Bean生命週期的構成

Bean的完整生命週期經歷了各類方法調用,這些方法能夠劃分爲如下幾類:spring

  1. Bean自身的方法: 這個包括了Bean自己調用的方法和經過配置文件中<bean>的init-method和destroy-method指定的方法
  2. Bean級生命週期接口方法: 這個包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這些接口的方法
  3. 容器級生命週期接口方法:這個包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個接口實現,通常稱它們的實現類爲「後處理器」。
  4. 工廠後處理器接口方法: 這個包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等很是有用的工廠後處理器接口的方法。工廠後處理器也是容器級的。在應用上下文裝配配置文件以後當即調用。

生命週期緩存

  建立  ----> 初始化 ---> 銷燬app

1. 實例化對象ide

2. setter注入,執行Bean的屬性依賴注入函數

3. BeanNameAware的setBeanName(), 若是實現該接口,則執行其setBeanName 方法post

4.BeanFactoryAware的setBeanFactory(), 若是實現該接口,則執行其setBeanFactory方法測試

5. BeanPostProcessor的processBeforeInitialization(),若是有關聯的processor,則在Bean初始化以前都會執行這個實例的processBeforeInitialization() 方法spa

 

綜上:3d

// 後置處理器
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    /**
     * 執行自定義init方法以前處理
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println( "3.[BeanPostProcessor] ---> postProcessBeforeInitialization 執行init方法[以前]處理") ;
        return bean;
    }

    /**
     * 執行自定義init方法以後處理
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println( "5.[BeanPostProcessor] ---> postProcessAfterInitialization 執行init方法[以後]處理") ;

        return bean;
    }
}

 

6. InitializingBean的afterPropertiesSet(), 若是實現了該接口,則執行其afterPropertiesSet()方法。Bean定義文件中定義init-method日誌

7.BeanPostProcessors的processAfterInitialization(),若是有關聯的processor,則在Bean初始化以前都會執行這個實例的processAfterInitialization()方法

8.DisposeablebBean的 destory(),在容器關閉時,若是Bean實現了這個接口,則執行他的destory()方法

9. Bean定義文件中定義destroy-method,在容器關閉時,能夠在Bean定義文件中使用「destory-method」定義的方法

 

注:

 1. 單例默認時在容器被加載時候會初始化

 2. 多例在每次獲取Bean的對象時候纔會去初始化

 


 

 

 bean 初始化 指的就是對象已經建立裏面全部的set方法都已經執行完畢了。 指定方法執行

   @Bean(initMethod , destory)   指定初始化和銷燬方法  同時在bean中建立這兩個方法

   init是在構造方法以前仍是以後執行? 無參構造!  對象先建立完成後才進行初始化!因此先執行無參構造函數!

 

補充到上面的過程:

  Bean的建立(執行構造函數) --> 初始化(自定義init方法) --> 銷燬

  調用close() 方法銷燬單例對象  

   注意:IOC容器使用Map結合存儲對象,clear() 清除對象

   看源碼:

進入查看:

繼續點擊查看:

看第一個:

持續跟進後就是 集合的 clear 方法了

 

 咱們能夠經過實現某些類 去進行初始化的操做!

 

開發使用的方式:


方法一: 經過@Bean指定init-method 和 destory-method

方法二: 經過讓Bean實現InitializingBean(定義初始化邏輯), DisposableBean(定義銷燬邏輯)

方法三: 使用JSR250(Java規範,不是Spring的): @PostConstruct: 在Bean建立完成而且賦值完成,來執行初始化方法。 @PreDestory: 在容器銷燬Bean以前通知咱們進行清理工做


 

方法二:

Bean:

@Component
public class LifeBean implements InitializingBean, DisposableBean {

    //構造函數
    public LifeBean() {
        System.out.println("LifeBean Constructor");
    }

    /** 接口InitializingBean的方法
     *  //解釋 對象有建立 確定也有給屬相賦值的過程!,對象賦值完畢之後才執行該方法  即: (afterPropertiesSet)中文:set方法都走完了時候執行該方法
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        //等同於 @Bean(init =" ")
        //解釋 對象有建立 確定也有給屬相賦值的過程!,對象賦值完畢之後才執行該方法
        System.out.println("LifeBean ********> 【InitializingBean.afterPropertiesSet】 ");
    }

    /**
     * 接口DisposableBean 的方法
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("LifeBean ********>【DisposableBean.destroy】");
    }
}

配置和掃包

@Configuration
@ComponentScan("com.toov5.config.beanTest.entity")
public class MyConfig {

}

啓動測試:

public class test {
    public test(){

    }
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext1 = new AnnotationConfigApplicationContext("com.toov5.config");
        applicationContext1.close();
//        System.out.println(applicationContext1);
    }
}

 

方法三

  註解代替了接口:

Bean:

@Component
public class LifeBean {

    //構造函數
    public LifeBean() {
        System.out.println("LifeBean Constructor");
    }
    @PostConstruct
    public void afterPropertiesSet() throws Exception {
        //等同於 @Bean(init =" ")
        //解釋 對象有建立 確定也有給屬相賦值的過程!,對象賦值完畢之後才執行該方法
        System.out.println("LifeBean ********> 【InitializingBean.afterPropertiesSet】 ");
    }

   @PreDestroy
    public void destroy() throws Exception {
        System.out.println("LifeBean ********>【DisposableBean.destroy】");
    }
}

效果是同樣的:

 

  

幾個重要的Aware接口:


1. ApplicationContextAware

過濾器中,不可使用註解方式獲取Bean對象。 作法: 單獨獲取上下文ApplicationContext

後置處理器,實現對Bean初始化加強功能

@Component
public class MyApplicationContext implements ApplicationContextAware {
    //開發時候常常作成全局的 進行使用
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        LifeBean lifeBean = applicationContext.getBean("lifeBean", LifeBean.class);
        System.out.println("result————————————————————"+lifeBean.toString());
    }
}

運行後:結果是沒問題的

問題: Spring底層中爲何可以實現ApplicationContextAware接口,就可以拿到ApplicationContext。

 

2. BeanNameAware 與 BeanFactoryAware

 Bean

@Component
public class LifeBean01 implements BeanNameAware, BeanFactoryAware {

    public LifeBean01() {
        System.out.println("LifeBean01 對象實例化完成");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("beanName:"+s);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("beanFactory:"+ beanFactory);
    }
}

配置類:

@Configuration
@ComponentScan("com.toov5.config.beanTest.entity")
public class MyConfig {

}

測試:

public class test {
    public test(){

    }
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext1 = new AnnotationConfigApplicationContext("com.toov5.config");
        applicationContext1.close();
//        System.out.println(applicationContext1);
    }
}

 

IOC容器初始化到哪裏獨享都是循環遍歷getBean方法。

getSingleton(beanName) 先查詢緩存有沒有,看下以前有沒有建立過

 

 

  Spring Bean生命週期中的後置處理器:  BeanPostProcessor接口


 從源碼能夠看到是 能夠在 init以前或者以後進行一系列的操做的

加上上面的那幾個接口一塊兒展現下:

 

 

後置處理器,單獨處理到別的bean裏面去, 其餘的bean(Spring 自帶的都會走這個方法了)。

init 以前以後,經過後置處理器對bean的初始化進行加強。 能夠作bean耗時統計,日誌打印等等。

Bean:

@Component
public class LifeBean01 implements BeanNameAware, BeanFactoryAware, InitializingBean {

    public LifeBean01() {
        System.out.println("1. -----------------》LifeBean01 對象實例化完成");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("2. -----------------》對象beanName:"+s);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("3. -----------------》beanFactory:"+ beanFactory);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5. -----------------》 bean init 方法執行");
    }
}

後置處理器:

// 後置處理器
@Component
public class MyBeanPostProcessor implements BeanPostProcessor{
    /**
     * 執行自定義init方法以前處理
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println( beanName + "==========> 執行init方法[以前]處理");
        return bean;
    }

    /**
     * 執行自定義init方法以後處理
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName +"==========>執行init方法[以後]處理");
        return bean;
    }
}

配置類:

@Configuration
@ComponentScan("com.toov5.config.beanTest.entity")
public class MyConfig {

}

測試:

public class test {
    public test(){

    }
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext1 = new AnnotationConfigApplicationContext("com.toov5.config");
//        applicationContext1.close();
//        System.out.println(applicationContext1);
    }
}

結果:

 

 生命週期流程圖:

 

描述:

  1.實例化對象 (能夠反射, 能夠new)

  2. 給對象屬性賦值

  3. 檢查是否有Aware依賴,若是有上述的哪些,就進行執行。

 

總結: 重點無非就是 Aware  和  後置處理器

從源碼中看 setApplicationContext() 方法是在前置獲取的。 經過postProcessBefore前置,裏面的默認方法獲取到上下文對象。

 

 

總結:

後置處理器:

@Component
public class LifeBean implements BeanNameAware, BeanFactoryAware ,
        InitializingBean, DisposableBean {

    @Override
    public void setBeanName(String s) {
        System.out.println("1.[BeanNameAware] ---> setBeanName");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("2.[BeanFactoryAware] ---> setBeanFactory");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("4.[InitializingBean] ---> afterPropertiesSet");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("6.[DisposableBean] ---> distory"  );
    }
}

 

Bean:

// 後置處理器
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    /**
     * 執行自定義init方法以前處理
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println( "3.[BeanPostProcessor] ---> postProcessBeforeInitialization 執行init方法[以前]處理") ;
        return bean;
    }

    /**
     * 執行自定義init方法以後處理
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println( "5.[BeanPostProcessor] ---> postProcessAfterInitialization 執行init方法[以後]處理") ;

        return bean;
    }
}

 

配置:

@Configuration
@ComponentScan("com.spring.test")
public class config {


}

 

測試

public class test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext1 = new AnnotationConfigApplicationContext(config.class);
        applicationContext1.close();
    }
}

相關文章
相關標籤/搜索