大廠高頻面試題Spring Bean生命周期最詳解

Spring作為當前Java最流行藕坯、最強大的輕量級框架团南。Spring Bean的生命周期也是面試高頻題,了解Spring Bean周期也能更好地幫助我們解決日常開發(fā)中的問題炼彪。程序員應(yīng)該都知道Spring的基礎(chǔ)容器是ApplicationContext吐根。應(yīng)很多粉絲的強烈建議,本文我來分析分析 ApplicationContext中Bean的生命周期辐马。ApplicationContext是頂層容器接口BeanFactory的實現(xiàn)類拷橘,因此,我們了解了ApplicationContext的生命周期邏輯喜爷,也基本上了解了其他類型容器的生命周期邏輯冗疮。

1 Spring生命周期流程圖

下面先來看一張Spring Bean完整的生命周期流程圖,下圖描述的是從Spring容器初始化Bean開始直到Spring容器銷毀Bean檩帐,所經(jīng)歷的關(guān)鍵節(jié)點术幔。

file

從上圖可以看出,Spring Bean的生命周期管理的基本思路是:在Bean出現(xiàn)之前湃密,先準備操作Bean的BeanFactory诅挑,然后操作完Bean四敞,所有的Bean也還會交給BeanFactory進行管理。在所有Bean操作準備BeanPostProcessor作為回調(diào)拔妥。在Bean的完整生命周期管理過程中忿危,經(jīng)歷了以下主要幾個步驟:

1.1 Bean創(chuàng)建前的準備階段

步驟1: Bean容器在配置文件中找到Spring Bean的定義以及相關(guān)的配置,如init-method和destroy-method指定的方法没龙。
步驟2: 實例化回調(diào)相關(guān)的后置處理器如BeanFactoryPostProcessor铺厨、BeanPostProcessor太颤、InstantiationAwareBeanPostProcessor等

1.2 創(chuàng)建Bean的實例

步驟3: Srping 容器使用Java反射API創(chuàng)建Bean的實例泡垃。
步驟4:掃描Bean聲明的屬性并解析。

1.3 開始依賴注入

步驟5:開始依賴注入疫鹊,解析所有需要賦值的屬性并賦值咬摇。
步驟6:如果Bean類實現(xiàn)BeanNameAware接口,則將通過傳遞Bean的名稱來調(diào)用setBeanName()方法煞躬。
步驟7:如果Bean類實現(xiàn)BeanFactoryAware接口肛鹏,則將通過傳遞BeanFactory對象的實例來調(diào)用setBeanFactory()方法。
步驟8:如果有任何與BeanFactory關(guān)聯(lián)的BeanPostProcessors對象已加載Bean恩沛,則將在設(shè)置Bean屬性之前調(diào)用postProcessBeforeInitialization()方法在扰。
步驟9:如果Bean類實現(xiàn)了InitializingBean接口,則在設(shè)置了配置文件中定義的所有Bean屬性后雷客,將調(diào)用afterPropertiesSet()方法芒珠。

1.4 緩存到Spring容器

步驟10: 如果配置文件中的Bean定義包含init-method屬性,則該屬性的值將解析為Bean類中的方法名稱搅裙,并將調(diào)用該方法皱卓。
步驟11:如果為Bean Factory對象附加了任何Bean 后置處理器,則將調(diào)用postProcessAfterInitialization()方法部逮。

1.5 銷毀Bean的實例

步驟12:如果Bean類實現(xiàn)DisposableBean接口娜汁,則當Application不再需要Bean引用時,將調(diào)用destroy()方法兄朋。
步驟13:如果配置文件中的Bean定義包含destroy-method屬性掐禁,那么將調(diào)用Bean類中的相應(yīng)方法定義。

2 代碼實戰(zhàn)演示

下面我們用一個簡單的Bean來演示并觀察一下Spring Bean完整的生命周期颅和。

2.1 準備Author類

1傅事、首先是一個簡單的Bean,調(diào)用Bean自身的方法和Bean級生命周期接口方法峡扩,為了方便演示蹭越,它實現(xiàn)了BeanNameAware、BeanFactoryAware有额、InitializingBean和DiposableBean這4個接口般又,同時添加2個init-method和destory-method方法彼绷,對應(yīng)配置文件中<bean>的init-method和destroy-method。具體代碼如下:


package com.tom.lifecycle;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;

@Slf4j
@Data
public class Author implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
    private String name;
    private String address;
    private int age;

    private BeanFactory beanFactory;

    private String beanName;

    public Author() {
        log.info("【構(gòu)造器】調(diào)用Tom類的構(gòu)造器實例化");
    }

    public void setName(String name) {
        log.info("【注入屬性】name");
        this.name = name;
    }

    public void setAddress(String address) {
        log.info("【注入屬性】address");
        this.address = address;
    }

    public void setAge(int age) {
        log.info("【注入屬性】age");
        this.age = age;
    }

    // 實現(xiàn)BeanFactoryAware接口的方法
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        log.info("【BeanFactoryAware接口】調(diào)用setBeanFactory方法");
        this.beanFactory = beanFactory;
    }

    // 實現(xiàn)BeanNameAware接口的方法
    public void setBeanName(String beanName) {
        log.info("【BeanNameAware接口】調(diào)用setBeanName方法");
        this.beanName = beanName;
    }

    // 實現(xiàn)DiposibleBean接口的方法
    public void destroy() throws Exception {
        log.info("【DiposibleBean接口】調(diào)用destroy方法");
    }

    // 實現(xiàn)InitializingBean接口的方法
    public void afterPropertiesSet() throws Exception {
        log.info("【InitializingBean接口】調(diào)用afterPropertiesSet方法");
    }

    // 通過<bean>的init-method屬性指定的初始化方法
    public void beanInit() {
        log.info("【init-method】調(diào)用<bean>的init-method屬性指定的初始化方法");
    }

    // 通過<bean>的destroy-method屬性指定的初始化方法
    public void beanDestory() {
        log.info("【destroy-method】調(diào)用<bean>的destroy-method屬性指定的初始化方法");
    }
}

在配置Spring配置文件中加入如下內(nèi)容:


    <bean id="author" class="com.tom.lifecycle.Author"
          init-method="beanInit"
          destroy-method="beanDestory"
          scope="singleton"
          p:name="Tom" p:address="湖南長沙" p:age="18"/>
            

2.2 演示BeanFactoryPostProcessor的執(zhí)行

1.創(chuàng)建GPBeanFactoryPostProcessor類茴迁,并實現(xiàn)BeanFactoryPostProcessor接口寄悯,具體代碼如下:


package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

@Slf4j
public class GPBeanFactoryPostProcessor implements BeanFactoryPostProcessor{

    public GPBeanFactoryPostProcessor() {
        super();
        log.info("調(diào)用BeanFactoryPostProcessor實現(xiàn)類構(gòu)造器!堕义!");
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        log.info("BeanFactoryPostProcessor調(diào)用postProcessBeanFactory方法");
        BeanDefinition bd = configurableListableBeanFactory.getBeanDefinition("author");
        bd.getPropertyValues().addPropertyValue("age", "16");
    }
}

2.在配置Spring配置文件中加入如下內(nèi)容:


    <bean id="beanFactoryPostProcessor" class="com.tom.lifecycle.GPBeanFactoryPostProcessor" />

3.編寫測試類BeanLifeCycleTest猜旬,具體代碼如下:


package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@Slf4j
public class BeanLifeCycleTest {

    public static void main(String[] args) {

        log.info("====== 開始初始化Spring容器 ========");

        ApplicationContext factory = new ClassPathXmlApplicationContext("application-beans.xml");

        log.info("====== 初始化Spring容器成功 ========");

        //獲取Author實例
        Author author = factory.getBean("author", Author.class);

        log.info(author.toString());

        log.info("====== 開始銷毀Spring容器 ========");

        ((ClassPathXmlApplicationContext) factory).registerShutdownHook();
    }

}

4.運行結(jié)果

運行結(jié)果如下:


15:49:12.477 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - 調(diào)用BeanPostProcessor實現(xiàn)類構(gòu)造器!倦卖!
15:49:12.494 [main] INFO com.tom.lifecycle.Author - 【構(gòu)造器】調(diào)用Tom類的構(gòu)造器實例化
15:49:12.527 [main] INFO com.tom.lifecycle.Author - 【注入屬性】address
15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【注入屬性】age
15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【注入屬性】name
15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【BeanNameAware接口】調(diào)用setBeanName方法
15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【BeanFactoryAware接口】調(diào)用setBeanFactory方法
15:49:12.528 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改
15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【InitializingBean接口】調(diào)用afterPropertiesSet方法
15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【init-method】調(diào)用<bean>的init-method屬性指定的初始化方法
15:49:12.528 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改
15:49:12.531 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 初始化Spring容器成功 ========
15:49:12.531 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - Author(name=Tom, address=湖南長沙, age=18, beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@26653222: defining beans [beanPostProcessor,author]; root of factory hierarchy, beanName=author)
15:49:12.531 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 開始銷毀Spring容器 ========
15:49:12.532 [Thread-0] INFO com.tom.lifecycle.Author - 【DiposibleBean接口】調(diào)用destroy方法
15:49:12.533 [Thread-0] INFO com.tom.lifecycle.Author - 【destroy-method】調(diào)用<bean>的destroy-method屬性指定的初始化方法

我們看到洒擦,整個執(zhí)行和我們一開始繪制的流程圖一致。但是為什么我們要實現(xiàn)BeanFactoryPostProcessor接口呢怕膛?我們進入到BeanFactoryPostProcessor的源碼如下:


package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}

BeanFactoryPostProcessor接口只有一個postProcessBeanFactory()方法熟嫩,BeanFactoryPostProcessor:在BeanFactory標準初始化之后可以進行修改。將加載所有Bean定義褐捻,但是還沒有實例化Bean掸茅。這個方法允許重新覆蓋或者添加屬性甚至快速的初始化bean。初次看到可能不知道postProcessBeanFactory()到底是干嘛的柠逞。要想透徹理解這個方法的作用昧狮,下面來進入到BeanFactoryPostProcessor的源碼,理解一下postProcessBeanFactory()的參數(shù)板壮,我們可以利用這些參數(shù)做一些操作逗鸣。

通過參數(shù)來看,只有一個ConfigurableListableBeanFactory類绰精,這個類的可以提供分析撒璧、修改Bean定義和預先實例化單例的功能。我們再進入到ConfigurableListableBeanFactory的源碼中:


public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

        //忽略被給定注入依賴類型 茬底,例如String
    void ignoreDependencyType(Class<?> var1);

        //略被給定注入依賴接口 沪悲。這個通常被使用由ApplicationContext去注冊依賴,可以以多種方式實現(xiàn)阱表。例如BeanFactory通過BeanFactoryAware殿如,ApplicationContext 通過ApplicationContextAware。默認情況下最爬,僅BeanFactoryAware接口是被忽略涉馁,需要忽略其他接口,調(diào)用此方法
    void ignoreDependencyInterface(Class<?> var1);

        //注冊一個特定類型依賴伴隨著相應(yīng)的Autowired值爱致。這個是準備被用于應(yīng)該可以Autowire而不是在這個工廠被定義的Bean的工廠/上下文引用烤送。例如 將ApplicationContext類型的依賴項解析為Bean所在的ApplicationContext實例。注意~在普通的BeanFactory中沒有注冊這樣的默認類型糠悯,甚至連BeanFactory接口本身都沒有
    void registerResolvableDependency(Class<?> var1, Object var2);

        //確認這個被指定的Bean是否是一個Autowire候選帮坚,將被注入到其他聲明匹配類型的依賴的Bean中
    boolean isAutowireCandidate(String var1, DependencyDescriptor var2) throws NoSuchBeanDefinitionException;

        //根據(jù)指定的beanName返回被注冊的Bean定義妻往,允許訪問其屬性值和構(gòu)造函數(shù)參數(shù)值(可以在BeanFactory后期處理期間被修改)。這個被返回的BeanDefinition對象不應(yīng)該是副本而是原始在工廠被注冊的试和。這意味著如果需要它可以被轉(zhuǎn)換為更具體的實現(xiàn)類型讯泣。注意這個方法只能獲得本地工廠BeanDefinition
    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

        //凍結(jié)全部Bean定義,給被注冊的Bean定義發(fā)信號告訴它們今后不再被修改和進一步后續(xù)處理阅悍。它允許Factory去積極緩存Bean定義元數(shù)據(jù)
    void freezeConfiguration();

        //返回該工廠的BeanDefinnition是否被凍結(jié)
    boolean isConfigurationFrozen();

        //確保所有非懶加載的單例Bean被實例化好渠,包括FactoryBean
    void preInstantiateSingletons() throws BeansException;
}

通過以上演示和分析,我們應(yīng)該大概能夠了解ConfigurableListableBeanFactory的作用节视,基本就都是對于Bean定義的操作拳锚。至此我們還沒有看到BeanPostProcessor 和InstantiationAwareBeanPostProcessor的調(diào)用。下面我們把BeanPostProcessor 和InstantiationAwareBeanPostProcessor的實現(xiàn)補充上來寻行,再看完整的執(zhí)行流程

2.3 實現(xiàn)BeanPostProcessor

創(chuàng)建GPBeanPostProcessor類霍掺,并實現(xiàn)BeanPostProcessor 接口,具體代碼如下:


package com.tom.lifecycle;

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

@Slf4j
public class GPBeanPostProcessor implements BeanPostProcessor {

    public GPBeanPostProcessor(){
        log.info("調(diào)用BeanPostProcessor實現(xiàn)類構(gòu)造器0柚抗楔!");
    }
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        log.info("BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改");
        return o;
    }

    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        log.info("BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改");
        return o;
    }
}

ApplicationContext 可以在BeanDefinition中自動檢測到實現(xiàn)了BeanPostProcessor的Bean,并且把這些Bean應(yīng)用于隨后的Bean創(chuàng)建拦坠。普通的BeanFactory允許對后處理器進行程序化注冊,通過工廠應(yīng)用于所有Bean創(chuàng)建剩岳。BeanPostProcessor接口中主要有兩個方法:

方法名 解釋
postProcessBeforeInitialization 在Bean實例化回調(diào)(例如InitializingBean的afterPropertiesSet 或者一個定制的init-method)之前應(yīng)用此BeanPostProcessor
postProcessAfterInitialization 在bean實例化回調(diào)(例如InitializingBean的afterPropertiesSet 或者一個定制的init-method)之后應(yīng)用此BeanPostProcessor

2.4 實現(xiàn)InstantiationAwareBeanPostProcessor

創(chuàng)建GPInstantiationAwareBeanPostProcessor類贞滨,并實現(xiàn)InstantiationAwareBeanPostProcessorAdapter接口,具體代碼如下:


package com.tom.lifecycle;

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

import java.beans.PropertyDescriptor;

@Slf4j
public class GPInstantiationAwareBeanPostProcessor  extends InstantiationAwareBeanPostProcessorAdapter {

    public GPInstantiationAwareBeanPostProcessor() {
        super();
        log.info("調(diào)用InstantiationAwareBeanPostProcessorAdapter實現(xiàn)類構(gòu)造器E淖亍晓铆!");
    }

    // 接口方法、實例化Bean之前調(diào)用
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass,String beanName) throws BeansException {
        log.info("InstantiationAwareBeanPostProcessor調(diào)用postProcessBeforeInstantiation方法");
        return null;
    }

    // 接口方法绰播、實例化Bean之后調(diào)用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("InstantiationAwareBeanPostProcessor調(diào)用postProcessAfterInitialization方法");
        return bean;
    }

    // 接口方法骄噪、設(shè)置某個屬性時調(diào)用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        log.info("InstantiationAwareBeanPostProcessor調(diào)用postProcessPropertyValues方法");
        return pvs;
    }
}

實現(xiàn)InstantiationAwareBeanPostProcessorAdapter的Bean之后,可以在實例化成功之后蠢箩,做一些校驗或者補充些內(nèi)容或者把Bean包裝代理注入链蕊。實現(xiàn)InstantiationAwareBeanPostProcessorAdapter的Bean之后,不會影響容器正常處理每一個實例化的Bean谬泌,其子類僅僅只是根據(jù)需要覆蓋父類的方法滔韵。

注意,只有在實際需要 InstantiationAwareBeanPostProcessor 功能時才推薦此基類掌实。如果我們所需要的只是簡單的BeanPostProcessor功能陪蜻,那么直接實現(xiàn)更簡單的接口即可。

下面詳細介紹一下InstantiationAwareBeanPostProcessorAdapter接口中的所有方法:

方法名 解釋
postProcessBeforeInstantiation 在實例化目標Bean之前應(yīng)用此BeanPostProcessor贱鼻。這個返回的Bean也許是一個代理代替目標Bean宴卖,有效地抑制目標Bean的默認實例化滋将。如果此方法返回一個非空對象,則Bean的創(chuàng)建過程將被短路症昏。唯一的進一步處理被應(yīng)用是BeanPostProcessor.postProcessAfterInitialization(java.lang.Object, java.lang.String)方法(改變了Bean的生命周期實例化之后直接進入BeanPostProcessor.postProcessAfterInitialization)回調(diào)來自于配置好的BeanPostProcessors随闽。這個回調(diào)將僅被應(yīng)用于有Bean Class的BeanDefintions。特別是齿兔,它不會應(yīng)用于采用”factory-method“的Bean橱脸。后處理器可以實現(xiàn)擴展的SmartInstantiationAwareBeanPostProcessor接口,以便預測它們將返回的Bean對象的類型
postProcessPropertyValues 在工廠將給定的屬性值應(yīng)用到給定的Bean之前分苇,對給定的屬性值進行后處理添诉。允許檢查全部依賴是否已經(jīng)全部滿足,例如基于一個@Required在Bean屬性的Setter方法上医寿。還允許替換要應(yīng)用的屬性值栏赴,通常通過基于原始的PropertyValues創(chuàng)建一個新的MutablePropertyValues實例,添加或刪除特定的值
postProcessAfterInitialization 在Bean初始化回調(diào)(如InitializingBean的afterPropertiesSet或者定制的init-method)之后靖秩,應(yīng)用這個BeanPostProcessor去給一個新的Bean實例须眷。Bean已經(jīng)配置了屬性值,返回的Bean實例可能已經(jīng)被包裝沟突。
如果是FactoryBean花颗,這個回調(diào)將為FactoryBean實例和其他被FactoryBean創(chuàng)建的對象所調(diào)用。這個post-processor可以通過相應(yīng)的FactoryBean實例去檢查決定是否應(yīng)用FactoryBean或者被創(chuàng)建的對象或者兩個都有惠拭。這個回調(diào)在一個由InstantiationAwareBeanPostProcessor短路的觸發(fā)之后將被調(diào)用

2.5 修改配置文件

完整的配置文件內(nèi)容如下:


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

        <bean id="beanPostProcessor" class="com.tom.lifecycle.GPBeanPostProcessor" />

        <bean id="beanFactoryPostProcessor" class="com.tom.lifecycle.GPBeanFactoryPostProcessor" />

        <bean id="instantiationAwareBeanPostProcessor" class="com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor" />


        <bean id="author" class="com.tom.lifecycle.Author"
                init-method="beanInit"
                destroy-method="beanDestory"
                scope="singleton"
                p:name="Tom" p:address="湖南長沙" p:age="18"/>

</beans>

2.6 運行結(jié)果

最后扩劝,我們再次運行BeanLifeCycleTest測試類,看到如下運行結(jié)果:

15:56:20.030 [main] INFO com.tom.lifecycle.GPBeanFactoryPostProcessor - 調(diào)用BeanFactoryPostProcessor實現(xiàn)類構(gòu)造器V案ā棒呛!
15:56:20.045 [main] INFO com.tom.lifecycle.GPBeanFactoryPostProcessor - BeanFactoryPostProcessor調(diào)用postProcessBeanFactory方法
15:56:20.046 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - 調(diào)用BeanPostProcessor實現(xiàn)類構(gòu)造器!域携!
15:56:20.047 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - 調(diào)用InstantiationAwareBeanPostProcessorAdapter實現(xiàn)類構(gòu)造器4孛搿!
15:56:20.051 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor調(diào)用postProcessBeforeInstantiation方法
15:56:20.052 [main] INFO com.tom.lifecycle.Author - 【構(gòu)造器】調(diào)用Tom類的構(gòu)造器實例化
15:56:20.069 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor調(diào)用postProcessPropertyValues方法
15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【注入屬性】address
15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【注入屬性】age
15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【注入屬性】name
15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【BeanNameAware接口】調(diào)用setBeanName方法
15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【BeanFactoryAware接口】調(diào)用setBeanFactory方法
15:56:20.093 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改
15:56:20.093 [main] INFO com.tom.lifecycle.Author - 【InitializingBean接口】調(diào)用afterPropertiesSet方法
15:56:20.093 [main] INFO com.tom.lifecycle.Author - 【init-method】調(diào)用<bean>的init-method屬性指定的初始化方法
15:56:20.093 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改
15:56:20.093 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor調(diào)用postProcessAfterInitialization方法
15:56:20.097 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 初始化Spring容器成功 ========
15:56:20.098 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - Author(name=Tom, address=湖南長沙, age=16, beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@26653222: defining beans [beanPostProcessor,beanFactoryPostProcessor,instantiationAwareBeanPostProcessor,author]; root of factory hierarchy, beanName=author)
15:56:20.098 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 開始銷毀Spring容器 ========
15:56:20.099 [Thread-0] INFO com.tom.lifecycle.Author - 【DiposibleBean接口】調(diào)用destroy方法
15:56:20.100 [Thread-0] INFO com.tom.lifecycle.Author - 【destroy-method】調(diào)用<bean>的destroy-method屬性指定的初始化方法

3 Spring Bean生命周期運行時序圖

最后我們來看一下完整的執(zhí)行時序圖:

file

關(guān)注『 Tom彈架構(gòu) 』回復“Spring”可獲取完整源碼秀鞭。

本文為“Tom彈架構(gòu)”原創(chuàng)趋观,轉(zhuǎn)載請注明出處。技術(shù)在于分享气筋,我分享我快樂拆内!
如果本文對您有幫助,歡迎關(guān)注和點贊宠默;如果您有任何建議也可留言評論或私信麸恍,您的支持是我堅持創(chuàng)作的動力。關(guān)注『 Tom彈架構(gòu) 』可獲取更多技術(shù)干貨!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抹沪,一起剝皮案震驚了整個濱河市刻肄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌融欧,老刑警劉巖敏弃,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異噪馏,居然都是意外死亡麦到,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門欠肾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓶颠,“玉大人,你說我怎么就攤上這事刺桃〈饬埽” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵瑟慈,是天一觀的道長桃移。 經(jīng)常有香客問我,道長葛碧,這世上最難降的妖魔是什么借杰? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮进泼,結(jié)果婚禮上第步,老公的妹妹穿的比我還像新娘。我一直安慰自己缘琅,他們只是感情好,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布廓推。 她就那樣靜靜地躺著刷袍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪樊展。 梳的紋絲不亂的頭發(fā)上呻纹,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機與錄音专缠,去河邊找鬼雷酪。 笑死,一個胖子當著我的面吹牛涝婉,可吹牛的內(nèi)容都是我干的哥力。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吩跋!你這毒婦竟也來了寞射?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤锌钮,失蹤者是張志新(化名)和其女友劉穎桥温,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體梁丘,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡侵浸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了氛谜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掏觉。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖混蔼,靈堂內(nèi)的尸體忽然破棺而出履腋,到底是詐尸還是另有隱情,我是刑警寧澤惭嚣,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布遵湖,位于F島的核電站,受9級特大地震影響晚吞,放射性物質(zhì)發(fā)生泄漏延旧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一槽地、第九天 我趴在偏房一處隱蔽的房頂上張望迁沫。 院中可真熱鬧,春花似錦捌蚊、人聲如沸集畅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挺智。三九已至,卻和暖如春窗宦,著一層夾襖步出監(jiān)牢的瞬間赦颇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工赴涵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留媒怯,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓髓窜,卻偏偏與公主長得像扇苞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容