Spring源碼深度解析,Spring源碼以及Bean的生命週期(五)(附代碼示例:)

五)Bean 的生命週期,創建---初始化---銷燬的過程

目錄

五)Bean 的生命週期,創建---初始化---銷燬的過程

一 ,  指定初始化方法 init-method 方法​   

二 ,指定銷燬 destory-method 方法

三,實現 InitializingBean 接口的 afterPropertiesSet()方法,當beanFactory 創建好對象,且把bean所有屬性設置好之後,相當於初始化方法。

實現 DisposableBean 的destory(),方法 當bean銷燬時,會把單例bean 進行銷燬

四,   可以使用JSR250規則定義的(java規範)兩個註解來實現,JDK自帶

五,Bean 的後置處理器,在 Bean 初始化之前調用進行攔截,在 bean 初始化前後進行一些處理工作,使用BeanPostProcessors 控制  Bean的生命週期。

實現  BeanPostProcessors兩個接口即可:

六 :項目Demo


一 ,  指定初始化方法 init-method 方法

  • 單實例 Bean,可以正常調用初始化和銷燬方法
  • 多實例的 Bean,容器只負責初始化,但不會管理bean,容器關閉時不會調用銷燬方法

    示例代碼:===》   項目 源碼  ====》  Cap8包:  xml 方式 指定

<!--創建Bike 類 bike 實例, 自定義初始化方法 init(),自定義銷燬方法 destory()-->
	<bean id="bike" class="com.enjoy.Cap8.bean.Bike" init-method="init" destroy-method="destory"></bean>

   註解實現===》項目 源碼  ====》  Cap8包:   (單實例模式下在容器創建之前實例化  Bean )     

//自定義初始化方法, 銷燬方法
    @Bean(initMethod = "init",destroyMethod = "destory")
    public Bike bike(){
        System.out.println("公交車到站了====》註冊到bean");
        return new Bike();
    }

 

public class Bike {

     public  Bike(){
         System.out.println("有一位乘客上車了=====>調類的構造方法");
     }

     //自定義bean 初始化方法
     public void init(){
         System.out.println("車啓動了====》 bean初始化方法");
     }

     //自定義bean 銷燬方法
     public void destory(){
         System.out.println("車爆炸了====》bean銷燬方法,關閉容器");
     }
}

  測試結果:

@Test
    public static void main(String[] args){
        //創建上下文對象
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);


        app.close();

    }

 

註解實現===》項目 源碼  ====》  Cap8包(多實例,容器在創建之前 不會去實例化 Bean ,只有當 getBean()  的時候纔會去 創建實例 )   

//自定義初始化方法, 銷燬方法,多實例模式下
    @Scope("prototype")
    @Bean(initMethod = "init",destroyMethod = "destory")
    public Bike bike(){
        System.out.println("公交車到站了====》註冊到bean");
        return new Bike();
    }

  Bike  與上面一致   測試 :

 @Test
    public static void main(String[] args){
        //創建上下文對象
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
        System.out.println("容器創建完成");
        //app.getBean("bike");

        app.close();

    }

   當我沒有去getBean 的時候,  Bean 並沒有實例化

@Test
    public static void main(String[] args){
        //創建上下文對象
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
        System.out.println("容器創建完成");
        app.getBean("bike");

        app.close();

    }

  結果顯而易見,  在容器創建完成之後getBean()  纔會去 創建 Bean  的實例 ,並且沒有調用銷燬方法

 

實現原理: 源碼跟蹤  

   

二 ,指定銷燬 destory-method 方法

              示例代碼:見   5.1 代碼   ====》項目源碼  Cap8;

三,實現 InitializingBean 接口的 afterPropertiesSet()方法,當beanFactory 創建好對象,且把bean所有屬性設置好之後,相當於初始化方法。

實現 DisposableBean destory(),方法 當bean銷燬時,會把單例bean 進行銷燬

示例源碼: ====》項目源碼  Cap8;

// 將 類註解爲註解,讓容器掃描注入bean
@Component
public class Volkswagen implements InitializingBean, DisposableBean {

    public Volkswagen(){
        System.out.println("構造方法, 大衆cc,買到手");
    }

    //實現 DisposableBean 接口, destroy 銷燬方法
    @Override
    public void destroy() throws Exception {
        System.out.println("大衆cc,沒了。。===》 容器銷燬");
    }

    //實現 InitializingBean 接口, afterPropertiesSet() 初始化方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("大衆cc,最愛。。===》 bean初始化");
    }
}

在配置類 增加掃描註解 將 該包下面的掃描到容器中 

@Configuration
//掃描包下所有組件,並注入bean 到容器
@ComponentScan("com.enjoy.Cap8.bean")
public class Cap8MainConfigOfLifeCycle {

    //自定義初始化方法, 銷燬方法,多實例模式下
    @Scope("prototype")
    @Bean(initMethod = "init",destroyMethod = "destory")
    public Bike bike(){
        System.out.println("公交車到站了====》註冊到bean");
        return new Bike();
    }

}

測試:

 @Test
    public static void main(String[] args){
        //創建上下文對象
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
        System.out.println("容器創建完成");
        //System.out.println(app.getBean("bike"));
        System.out.println(app.getBean("volkswagen"));
        app.close();

    }

四,   可以使用JSR250規則定義的(java規範)兩個註解來實現,JDK自帶

  •           @PostConstruct : 在Bean 創建完成,且shu屬於賦值完成後進行初始化,屬於JDK規範的註解
  •           @PreDestroy   :    在Bean  將被移除之前進行通知,在容器銷燬之前進行清理工作

示例源碼: ====》項目源碼  Cap8;

@Component
public class Benz {
    public Benz(){
        System.out.println("構造方法,買了一輛奔馳");
    }

    //使用JSR250規則定義 JDK 自帶註解   初始化 bean
    @PostConstruct
    public void init(){
        System.out.println("奔馳漏油了 ====》初始bean");
    }

    //使用JSR250規則定義 JDK 自帶註解   容器銷燬
    @PreDestroy
    public void destroy(){
        System.out.println("奔馳爆炸了 ====》容器銷燬");
    }
}

在配置類 增加掃描註解 將 該包下面的掃描到容器中 

@Configuration
//掃描包下所有組件,並注入bean 到容器
@ComponentScan("com.enjoy.Cap8.bean")
public class Cap8MainConfigOfLifeCycle {

    //自定義初始化方法, 銷燬方法,多實例模式下
    @Scope("prototype")
    @Bean(initMethod = "init",destroyMethod = "destory")
    public Bike bike(){
        System.out.println("公交車到站了====》註冊到bean");
        return new Bike();
    }

}

測試 

 @Test
    public static void main(String[] args){
        //創建上下文對象
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
        System.out.println("容器創建完成");
        //System.out.println(app.getBean("bike"));
        //System.out.println(app.getBean("volkswagen"));
        System.out.println(app.getBean("benz"));
        app.close();

    }

五,Bean 的後置處理器,在 Bean 初始化之前調用進行攔截,在 bean 初始化前後進行一些處理工作,使用BeanPostProcessors 控制  Bean的生命週期。

實現  BeanPostProcessors兩個接口即可:

  •  postProcessBeforelnitialization()    在Bean  初始化之前       進行攔截 增強
  •  postProcessAfterInitalization()        在Bean  初始化之後       進行攔截 增強

Spring 底層對 BeanPostProcessor 的使用,包括 bean 的賦值,注入其他組件,生命週期註解功能等。 如:

  • ApplicationContextAwareProcesspor  接口    這個後置處理器其實就是判斷我們的 bean 有沒有實現  ApplicationContextAware 這個接口  ,並處理相應的邏輯,
  • BeanValidationPostProcess 接口  數據校驗
  • InitDestroyAnnotationBeanPostProcessor 接口  此處理器  是用來處理   上述 5.4@PostConstruct  @PreDestroy   讓 容器 找到 init 方法 和  destroy 方法 

 

    示例源碼: ====》項目源碼  Cap8;

 實現  BeanPostProcessors 接口, 裏面的兩個方法

@Component
public class Bmw implements BeanPostProcessor {

    /**Aop 在初始化bean 攔截 進行增強 做一些操作,如 任何bean 初始化回調或自定義初始化方法之前,
     *將此BeanPostProcessor應用於給定的新bean實例 bean已經填充了屬性值。 返回的bean實例可能是原始實例的包裝器
     **/
    @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization=====>"+bean+"===>"+beanName);
        return bean;
    }
    /**Aop 在初始化bean 攔截 進行增強 做一些操作,如 一般的Aop 事務 在事件之後 commit,
    *在bean初始完後 攔截 增強 對於FactoryBean,將爲FactoryBean 實例和FactoryBean創建的對象調用此回調。 
     * 處理器可以通過相應的檢查來決定是應用於FactoryBean還是應用於創建的對象。 與所有其他BeanPostProcessor回調相比
     **/
   @Override
   public  Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
       System.out.println("postProcessAfterInitialization=====>"+bean+"===>"+beanName);
        return bean;
    }
}

 

配置類 ; 爲了便於觀察   當前 只是 掃描到  benz 這個類  

@Configuration
//掃描包下所有組件,並注入bean 到容器
@ComponentScan("com.enjoy.Cap8.bean")
public class Cap8MainConfigOfLifeCycle {

    //自定義初始化方法, 銷燬方法,多實例模式下
    //@Scope("prototype")
    //@Bean(initMethod = "init",destroyMethod = "destory")
    public Bike bike(){
        System.out.println("公交車到站了====》註冊到bean");
        return new Bike();
    }

}

測試:

 @Test
    public static void main(String[] args){
        //創建上下文對象
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
        System.out.println("容器創建完成");
        //System.out.println(app.getBean("bike"));
        //System.out.println(app.getBean("volkswagen"));
        System.out.println(app.getBean("benz"));
        app.close();

    }

觀察結果

    

六 :項目Demo

Spring源碼深度解析,(附代碼示例 碼雲地址: https://gitee.com/Crazycw/SpringCode.git)

參考資料:  https://docs.spring.io/spring/docs/4.3.18.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/

請看下篇: Spring源碼深度解析,初始Spring源碼(六)(附代碼示例:)
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章