探索Spring系列(一)Spring容器和Bean的生命週期

小橘子2222發表於2019-01-15

前言

不知不覺畢業已經三年有餘,前面的時間一直忙於工作上的事情,最近稍微有點空閒時間,就準備梳理下自己的知識體系,發覺得自己的知識體系很是混亂和不足,正巧手中有一些書籍,藉此機會好好學習和梳理一番,也希望自己的一點小小記錄能分享給各位,帶給大家一些收穫。

一:Spring容器

Spring容器負責建立,管理物件,物件的整個生命週期都是由容器(container)負責的,下面是Spring中容器的介面的實現類

探索Spring系列(一)Spring容器和Bean的生命週期
我們在開發中接觸和使用最多的就是其中的基於註解的配置類的AnnotationConfigWebApplicationContext上下文,和基於xml配置的XmlWebApplicationContext上下文,當然Spring容器的還要一個重要的功能DI(依賴注入)這個功能我將在下個章節學習

二:Bean的生命週期

瞭解Bean的生命週期,有助於我們理解Bean在容器的運作過程,何時建立,何時呼叫,何時銷燬, spring對Bean例項化過程主要有以下幾個階段:

1:spring對bean進行例項化
2:spring將值和bean的引用注入到bean的對應屬性中
3:如果bean實現了BeanNameAware介面,Spring將bean的ID傳遞給setBeanName()方法
4:如果Bean實現了BeanFactoryAware介面,Spring將呼叫setBeanFactory()方法,將BeanFactory容器例項傳入
5:如果bean實現了ApplicationContextAware介面,Spring將呼叫setApplicationContext()方法,將bean所在的應用上下文的引用傳遞進來
6:如果bean實現了BeanPostProcessor介面,Spring將呼叫它的postProcessorBeforeInitialization()q前置處理方法
7:如果bean實現了InitializingBean介面,Spring將呼叫它們的afterPropertiesSet()方方法,類似的如果bean使用了init-method宣告瞭初始化方法,該方法也會被呼叫
8:如果bean實現了BeanPostProcessor介面,Spring將呼叫它們的postProcessorAfterInitialization()後置處理方法
9:此時bean已經準備就虛了,可以被應用程式使用了,它們將一直駐留在應用程式上下文中,直到該應用上下文被銷燬
10:如果bean實現了DisposableBean介面,Spring將呼叫它的destroy()介面方法,同樣,如果bean使用了destroy-method宣告瞭銷燬方法,該方法也會被呼叫

下面我們實際寫程式碼測試一下

首先我們定義一個實體類並且實現eanNameAware, BeanFactoryAware,ApplicationContextAware, InitializingBean, BeanPostProcessor, DisposableBean介面重寫父類的方法

package com.lly.springtest1.entity;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @ClassName GirlFriendEntity
 * @Description bean實體類
 * @Author lly
 * @Date 2019/1/16
 * @Version 1.0
 **/
@Slf4j
public class GirlFriendEntity implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {

    private String name;


    public GirlFriendEntity() {
        log.info("呼叫GirlFriendEntity的無引數構造器方法");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        log.info("BeanFactoryAware呼叫setBeanFactory方法將BeanFactory例項傳入");
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        log.info("對name屬性進行賦值");
        this.name = name;
    }

    @Override
    public void setBeanName(String s) {
        log.info("BeanNameAware呼叫setBeanName方法,將bean的name注入");
    }

    @Override
    public void destroy() throws Exception {
        log.info("DisposableBean呼叫destroy方法");

    }

    @Override
    public void afterPropertiesSet() throws Exception {

        log.info("InitializingBean呼叫afterPropertiesSet方法");
    }

    //自定義的初始化方法
    @PostConstruct
    public void myInit() {
        log.info("呼叫自定義的init方法");
    }

    //自定義銷燬方法
    @PreDestroy
    public void myDestroy() {
        log.info("呼叫自定義的destroy方法");
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("呼叫ApplicationContext方法的setApplicationContext注入上下文");
    }
}

複製程式碼

接著我們來定義個繼承BeanPostProcessor的類來觀察

package com.lly.springtest1.entity;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @ClassName MyBeanPostProcessor
 * @Description
 * @Author lly
 * @Date 2019/1/16
 * @Version 1.0
 **/
@Slf4j
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean.getClass() == GirlFriendEntity.class) {
            log.info("BeanPostProcessor呼叫postProcessBeforeInitialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean.getClass() == GirlFriendEntity.class) {
            log.info("BeanPostProcessor呼叫postProcessAfterInitialization");
        }
        return bean;
    }

}

複製程式碼

然後啟動容器看看bean初始化的具體流程

package com.lly.springtest1.entity;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @ClassName Test
 * @Description 
 * @Author lly
 * @Date 2019/1/16
 * @Version 1.0
 **/
@Configuration
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Test.class);
        context.close();
    }

    @Bean
    public MyBeanPostProcessor getBean() {
        return new MyBeanPostProcessor();
    }

    @Bean
    public GirlFriendEntity getGirl() {
        GirlFriendEntity girl = new GirlFriendEntity();
        girl.setName("穎寶");
        return girl;
    }
}

複製程式碼

列印結果如下

探索Spring系列(一)Spring容器和Bean的生命週期
我們可以清晰看到bean的整個生命週期

另外關於自定義初始化和銷燬的方法除了有上述的註解方式,還可以使用這種方式,效果是一樣

探索Spring系列(一)Spring容器和Bean的生命週期

探索Spring系列(一)Spring容器和Bean的生命週期

相關文章