大廠高頻面試題Spring Bean生命周期詳解
Spring作為當(dāng)前Java最流行、最強(qiáng)大的輕量級(jí)框架。Spring Bean的生命周期也是面試高頻題,了解Spring Bean周期也能更好地幫助我們解決日常開(kāi)發(fā)中的問(wèn)題。程序員應(yīng)該都知道Spring的基礎(chǔ)容器是ApplicationContext。應(yīng)很多粉絲的強(qiáng)烈建議,本文我來(lái)分析分析 ApplicationContext中Bean的生命周期。ApplicationContext是頂層容器接口BeanFactory的實(shí)現(xiàn)類,因此,我們了解了ApplicationContext的生命周期邏輯,也基本上了解了其他類型容器的生命周期邏輯。
一、Spring生命周期流程圖
下面先來(lái)看一張Spring Bean完整的生命周期流程圖,下圖描述的是從Spring容器初始化Bean開(kāi)始直到Spring容器銷毀Bean,所經(jīng)歷的關(guān)鍵節(jié)點(diǎn)。
從上圖可以看出,Spring Bean的生命周期管理的基本思路是:在Bean出現(xiàn)之前,先準(zhǔn)備操作Bean的BeanFactory,然后操作完Bean,所有的Bean也還會(huì)交給BeanFactory進(jìn)行管理。在所有Bean操作準(zhǔn)備BeanPostProcessor作為回調(diào)。在Bean的完整生命周期管理過(guò)程中,經(jīng)歷了以下主要幾個(gè)步驟:
1.1 Bean創(chuàng)建前的準(zhǔn)備階段
步驟1:Bean容器在配置文件中找到Spring Bean的定義以及相關(guān)的配置,如init-method和destroy-method指定的方法。步驟2:實(shí)例化回調(diào)相關(guān)的后置處理器如BeanFactoryPostProcessor、BeanPostProcessor、InstantiationAwareBeanPostProcessor等
1.2 創(chuàng)建Bean的實(shí)例
步驟3:Srping 容器使用Java反射API創(chuàng)建Bean的實(shí)例。步驟4:掃描Bean聲明的屬性并解析。
1.3 開(kāi)始依賴注入
步驟5:開(kāi)始依賴注入,解析所有需要賦值的屬性并賦值。步驟6:如果Bean類實(shí)現(xiàn)BeanNameAware接口,則將通過(guò)傳遞Bean的名稱來(lái)調(diào)用setBeanName()方法。步驟7:如果Bean類實(shí)現(xiàn)BeanFactoryAware接口,則將通過(guò)傳遞BeanFactory對(duì)象的實(shí)例來(lái)調(diào)用setBeanFactory()方法。步驟8:如果有任何與BeanFactory關(guān)聯(lián)的BeanPostProcessors對(duì)象已加載Bean,則將在設(shè)置Bean屬性之前調(diào)用postProcessBeforeInitialization()方法。步驟9:如果Bean類實(shí)現(xiàn)了InitializingBean接口,則在設(shè)置了配置文件中定義的所有Bean屬性后,將調(diào)用afterPropertiesSet()方法。
1.4 緩存到Spring容器
步驟10:如果配置文件中的Bean定義包含init-method屬性,則該屬性的值將解析為Bean類中的方法名稱,并將調(diào)用該方法。步驟11:如果為Bean Factory對(duì)象附加了任何Bean 后置處理器,則將調(diào)用postProcessAfterInitialization()方法。
1.5 銷毀Bean的實(shí)例
步驟12:如果Bean類實(shí)現(xiàn)DisposableBean接口,則當(dāng)Application不再需要Bean引用時(shí),將調(diào)用destroy()方法。步驟13:如果配置文件中的Bean定義包含destroy-method屬性,那么將調(diào)用Bean類中的相應(yīng)方法定義。
二、代碼實(shí)戰(zhàn)演示
下面我們用一個(gè)簡(jiǎn)單的Bean來(lái)演示并觀察一下Spring Bean完整的生命周期。
2.1 準(zhǔn)備Author類
1、首先是一個(gè)簡(jiǎn)單的Bean,調(diào)用Bean自身的方法和Bean級(jí)生命周期接口方法,為了方便演示,它實(shí)現(xiàn)了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這4個(gè)接口,同時(shí)添加2個(gè)init-method和destory-method方法,對(duì)應(yīng)配置文件中的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)造器實(shí)例化");
- }
- 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;
- }
- // 實(shí)現(xiàn)BeanFactoryAware接口的方法
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- log.info("【BeanFactoryAware接口】調(diào)用setBeanFactory方法");
- this.beanFactory = beanFactory;
- }
- // 實(shí)現(xiàn)BeanNameAware接口的方法
- public void setBeanName(String beanName) {
- log.info("【BeanNameAware接口】調(diào)用setBeanName方法");
- this.beanName = beanName;
- }
- // 實(shí)現(xiàn)DiposibleBean接口的方法
- public void destroy() throws Exception {
- log.info("【DiposibleBean接口】調(diào)用destroy方法");
- }
- // 實(shí)現(xiàn)InitializingBean接口的方法
- public void afterPropertiesSet() throws Exception {
- log.info("【InitializingBean接口】調(diào)用afterPropertiesSet方法");
- }
- // 通過(guò)<bean>的init-method屬性指定的初始化方法
- public void beanInit() {
- log.info("【init-method】調(diào)用<bean>的init-method屬性指定的初始化方法");
- }
- // 通過(guò)<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="湖南長(zhǎng)沙" p:age="18"/>
2.2 演示BeanFactoryPostProcessor的執(zhí)行
1.創(chuàng)建GPBeanFactoryPostProcessor類,并實(shí)現(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實(shí)現(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.編寫測(cè)試類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("====== 開(kāi)始初始化Spring容器 ========");
- ApplicationContext factory = new ClassPathXmlApplicationContext("application-beans.xml");
- log.info("====== 初始化Spring容器成功 ========");
- //獲取Author實(shí)例
- Author author = factory.getBean("author", Author.class);
- log.info(author.toString());
- log.info("====== 開(kāi)始銷毀Spring容器 ========");
- ((ClassPathXmlApplicationContext) factory).registerShutdownHook();
- }
- }
4.運(yùn)行結(jié)果
運(yùn)行結(jié)果如下:
- 15:49:12.477 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - 調(diào)用BeanPostProcessor實(shí)現(xiàn)類構(gòu)造器!!
- 15:49:12.494 [main] INFO com.tom.lifecycle.Author - 【構(gòu)造器】調(diào)用Tom類的構(gòu)造器實(shí)例化
- 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對(duì)屬性進(jìn)行更改
- 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對(duì)屬性進(jìn)行更改
- 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=湖南長(zhǎng)沙, 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 - ====== 開(kāi)始銷毀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屬性指定的初始化方法
我們看到,整個(gè)執(zhí)行和我們一開(kāi)始繪制的流程圖一致。但是為什么我們要實(shí)現(xiàn)BeanFactoryPostProcessor接口呢?我們進(jìn)入到BeanFactoryPostProcessor的源碼如下:
- package org.springframework.beans.factory.config;
- import org.springframework.beans.BeansException;
- public interface BeanFactoryPostProcessor {
- void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
- }
BeanFactoryPostProcessor接口只有一個(gè)postProcessBeanFactory()方法,BeanFactoryPostProcessor:在BeanFactory標(biāo)準(zhǔn)初始化之后可以進(jìn)行修改。將加載所有Bean定義,但是還沒(méi)有實(shí)例化Bean。這個(gè)方法允許重新覆蓋或者添加屬性甚至快速的初始化bean。初次看到可能不知道postProcessBeanFactory()到底是干嘛的。要想透徹理解這個(gè)方法的作用,下面來(lái)進(jìn)入到BeanFactoryPostProcessor的源碼,理解一下postProcessBeanFactory()的參數(shù),我們可以利用這些參數(shù)做一些操作。
通過(guò)參數(shù)來(lái)看,只有一個(gè)ConfigurableListableBeanFactory類,這個(gè)類的可以提供分析、修改Bean定義和預(yù)先實(shí)例化單例的功能。我們?cè)龠M(jìn)入到ConfigurableListableBeanFactory的源碼中:
- public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
- //忽略被給定注入依賴類型 ,例如String
- void ignoreDependencyType(Class<?> var1);
- //略被給定注入依賴接口 。這個(gè)通常被使用由ApplicationContext去注冊(cè)依賴,可以以多種方式實(shí)現(xiàn)。例如BeanFactory通過(guò)BeanFactoryAware,ApplicationContext 通過(guò)ApplicationContextAware。默認(rèn)情況下,僅BeanFactoryAware接口是被忽略,需要忽略其他接口,調(diào)用此方法
- void ignoreDependencyInterface(Class<?> var1);
- //注冊(cè)一個(gè)特定類型依賴伴隨著相應(yīng)的Autowired值。這個(gè)是準(zhǔn)備被用于應(yīng)該可以Autowire而不是在這個(gè)工廠被定義的Bean的工廠/上下文引用。例如 將ApplicationContext類型的依賴項(xiàng)解析為Bean所在的ApplicationContext實(shí)例。注意~在普通的BeanFactory中沒(méi)有注冊(cè)這樣的默認(rèn)類型,甚至連BeanFactory接口本身都沒(méi)有
- void registerResolvableDependency(Class<?> var1, Object var2);
- //確認(rèn)這個(gè)被指定的Bean是否是一個(gè)Autowire候選,將被注入到其他聲明匹配類型的依賴的Bean中
- boolean isAutowireCandidate(String var1, DependencyDescriptor var2) throws NoSuchBeanDefinitionException;
- //根據(jù)指定的beanName返回被注冊(cè)的Bean定義,允許訪問(wèn)其屬性值和構(gòu)造函數(shù)參數(shù)值(可以在BeanFactory后期處理期間被修改)。這個(gè)被返回的BeanDefinition對(duì)象不應(yīng)該是副本而是原始在工廠被注冊(cè)的。這意味著如果需要它可以被轉(zhuǎn)換為更具體的實(shí)現(xiàn)類型。注意這個(gè)方法只能獲得本地工廠BeanDefinition
- BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
- //凍結(jié)全部Bean定義,給被注冊(cè)的Bean定義發(fā)信號(hào)告訴它們今后不再被修改和進(jìn)一步后續(xù)處理。它允許Factory去積極緩存Bean定義元數(shù)據(jù)
- void freezeConfiguration();
- //返回該工廠的BeanDefinnition是否被凍結(jié)
- boolean isConfigurationFrozen();
- //確保所有非懶加載的單例Bean被實(shí)例化,包括FactoryBean
- void preInstantiateSingletons() throws BeansException;
- }
通過(guò)以上演示和分析,我們應(yīng)該大概能夠了解ConfigurableListableBeanFactory的作用,基本就都是對(duì)于Bean定義的操作。至此我們還沒(méi)有看到BeanPostProcessor 和InstantiationAwareBeanPostProcessor的調(diào)用。下面我們把BeanPostProcessor 和InstantiationAwareBeanPostProcessor的實(shí)現(xiàn)補(bǔ)充上來(lái),再看完整的執(zhí)行流程
2.3 實(shí)現(xiàn)BeanPostProcessor
創(chuàng)建GPBeanPostProcessor類,并實(shí)現(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實(shí)現(xiàn)類構(gòu)造器?。?quot;);
- }
- public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
- log.info("BeanPostProcessor接口方法postProcessBeforeInitialization對(duì)屬性進(jìn)行更改");
- return o;
- }
- public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
- log.info("BeanPostProcessor接口方法postProcessAfterInitialization對(duì)屬性進(jìn)行更改");
- return o;
- }
- }
ApplicationContext 可以在BeanDefinition中自動(dòng)檢測(cè)到實(shí)現(xiàn)了BeanPostProcessor的Bean,并且把這些Bean應(yīng)用于隨后的Bean創(chuàng)建。普通的BeanFactory允許對(duì)后處理器進(jìn)行程序化注冊(cè),通過(guò)工廠應(yīng)用于所有Bean創(chuàng)建。BeanPostProcessor接口中主要有兩個(gè)方法:| 方法名 | 解釋 | | -------- | -------- | | postProcessBeforeInitialization | 在Bean實(shí)例化回調(diào)(例如InitializingBean的afterPropertiesSet 或者一個(gè)定制的init-method)之前應(yīng)用此BeanPostProcessor | | postProcessAfterInitialization | 在bean實(shí)例化回調(diào)(例如InitializingBean的afterPropertiesSet 或者一個(gè)定制的init-method)之后應(yīng)用此BeanPostProcessor |
2.4 實(shí)現(xiàn)InstantiationAwareBeanPostProcessor
創(chuàng)建GPInstantiationAwareBeanPostProcessor類,并實(shí)現(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實(shí)現(xiàn)類構(gòu)造器!!");
- }
- // 接口方法、實(shí)例化Bean之前調(diào)用
- @Override
- public Object postProcessBeforeInstantiation(Class beanClass,String beanName) throws BeansException {
- log.info("InstantiationAwareBeanPostProcessor調(diào)用postProcessBeforeInstantiation方法");
- return null;
- }
- // 接口方法、實(shí)例化Bean之后調(diào)用
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- log.info("InstantiationAwareBeanPostProcessor調(diào)用postProcessAfterInitialization方法");
- return bean;
- }
- // 接口方法、設(shè)置某個(gè)屬性時(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;
- }
- }
實(shí)現(xiàn)InstantiationAwareBeanPostProcessorAdapter的Bean之后,可以在實(shí)例化成功之后,做一些校驗(yàn)或者補(bǔ)充些內(nèi)容或者把Bean包裝代理注入。實(shí)現(xiàn)InstantiationAwareBeanPostProcessorAdapter的Bean之后,不會(huì)影響容器正常處理每一個(gè)實(shí)例化的Bean,其子類僅僅只是根據(jù)需要覆蓋父類的方法。
注意,只有在實(shí)際需要 InstantiationAwareBeanPostProcessor 功能時(shí)才推薦此基類。如果我們所需要的只是簡(jiǎn)單的BeanPostProcessor功能,那么直接實(shí)現(xiàn)更簡(jiǎn)單的接口即可。
下面詳細(xì)介紹一下InstantiationAwareBeanPostProcessorAdapter接口中的所有方法:
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="湖南長(zhǎng)沙" p:age="18"/>
- </beans>
2.6 運(yùn)行結(jié)果
最后,我們?cè)俅芜\(yùn)行BeanLifeCycleTest測(cè)試類,看到如下運(yùn)行結(jié)果:
- 15:56:20.030 [main] INFO com.tom.lifecycle.GPBeanFactoryPostProcessor - 調(diào)用BeanFactoryPostProcessor實(shí)現(xiàn)類構(gòu)造器??!
- 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實(shí)現(xiàn)類構(gòu)造器??!
- 15:56:20.047 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - 調(diào)用InstantiationAwareBeanPostProcessorAdapter實(shí)現(xiàn)類構(gòu)造器!!
- 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)造器實(shí)例化
- 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對(duì)屬性進(jìn)行更改
- 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對(duì)屬性進(jìn)行更改
- 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=湖南長(zhǎng)沙, 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 - ====== 開(kāi)始銷毀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屬性指定的初始化方法
三、Spring Bean生命周期運(yùn)行時(shí)序圖
最后我們來(lái)看一下完整的執(zhí)行時(shí)序圖: