前语

写《apollo更改装备刷新@ConfigurationProperties装备类》文章时发现触及到了spring bean生命周期相关知识,这是一个很好的关键去全面温故下它,之前也写过《spring 生命周期最详解》至目前为止有幸被阅读6w+次、200个小伙伴收藏,可是现在看来有些粗糙,想借此进一步稳固下。

根本的思路是:

  1. 全体有个概念的了解
  2. 对全体生命周期有个开端的感知
  3. 从头梳理下生命周期
    • 结合源码进一步了解
    • 首要看看扩展点
  4. 实际运用的举例

期望此次能更加通俗易懂、便利回忆。

了解全体

Spring容器只管理singleton效果域下的Bean,Spring能够精确地知道该Bean何时被创立,何时初始化完结,以及何时被毁掉。

而对于prototype的bean,spring 只负责创立,当容器创立了Bean的实例之后不会盯梢其生命周期,直接交给客户端代码管理

了解spring bean的生命周期能够在不同的阶段进行介入完结一些需求的操作,比如在bean现已注入依赖的特点bean之后咱们需求对特点bean进行自定义装备能够运用@PostContruct,比如在client类bean要毁掉之前需求开释连接能够运用@PreDestroy。

相比一般的java方针,咱们需求自己去区分这些生命周期阶段,语言并没有提供,只要一个Object#finalize能够在垃圾回收之前履行一些清理。

全体感知生命周期

package com.study.bean.lifecycle;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Slf4j
@ToString
public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean{
    private String name;
    private String address;
    private Integer phone;
    private BeanFactory beanFactory;
    private String beanName;
    public Person() {
        log.info("【结构器】调用Person的结构器实例化");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        log.info("[注入特点]name:{}",name);
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        log.info("[注入特点]address:{}",address);
        this.address = address;
    }
    public Integer getPhone() {
        return phone;
    }
    public void setPhone(Integer phone) {
        log.info("【注入特点】phone:{}",phone);
        this.phone = phone;
    }
    public BeanFactory getBeanFactory() {
        return beanFactory;
    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        log.info("【BeanFactoryAware接口】调用setBeanFactory办法,beanFactory:{}", beanFactory.getClass().getName());
        this.beanFactory = beanFactory;
    }
    public String getBeanName() {
        return beanName;
    }
    @Override
    public void setBeanName(String beanName) {
        log.info("【BeanNameAware接口】调用setBeanName办法,name:{}", beanName);
        this.beanName = beanName;
    }
    @Override
    public void destroy() throws Exception {
        log.info("【DiposibleBean接口】调用destory办法");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("【InitializingBean接口】调用afterPropertiesSet办法");
    }
    public void myInit() {
        log.info("【init-method】调用<bean>的init-method特点指定的初始化办法");
    }
    public void myDestory() {
        log.info("【destory-method】调用<bean>的destroy-method特点指定的初始化办法");
    }
    @PostConstruct
    public void postConstruct() {
        log.info("调用@PostConstruct注解的办法");
    }
    @PreDestroy
    public void myPreDestroy() {
        log.info("调用@PreDestroy注解的办法");
    }
}
package com.study.bean.lifecycle;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        log.info("InstantiationAwareBeanPostProcessorAdapter调用postProcessBeforeInstantiation办法");
        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        log.info("InstantiationAwareBeanPostProcessorAdapter调用postProcessAfterInstantiation办法");
        return super.postProcessAfterInstantiation(bean, beanName);
    }
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        log.info("InstantiationAwareBeanPostProcessorAdapter调用postProcessProperties办法,pvs:{}", JSON.toJSONString(pvs.getPropertyValues()));
        return super.postProcessProperties(pvs, bean, beanName);
    }
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.info("InstantiationAwareBeanPostProcessorAdapter调用postProcessBeforeInitialization办法");
        return super.postProcessBeforeInitialization(bean, beanName);
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("InstantiationAwareBeanPostProcessorAdapter调用postProcessAfterInitialization");
        return super.postProcessAfterInitialization(bean, beanName);
    }
}
package com.study.bean.lifecycle;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.info("BeanPostProcessor接口调用postProcessBeforeInitialization");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("BeanPostProcessor接口调用postProcessAfterInitialization");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}
package com.study.bean.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;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        log.info("调用BeanFactoryPostProcessor#postProcessBeanFactory");
        BeanDefinition bd = beanFactory.getBeanDefinition("person");
        bd.getPropertyValues().addPropertyValue("phone", "110");
    }
}
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"
       default-init-method="init_method" default-destroy-method="destroy_method">
    <context:component-scan base-package="com.study.bean.lifecycle"/>
    <bean id="person" class="com.study.bean.lifecycle.Person" init-method="myInit" destroy-method="myDestory"
          p:name="张三" p:address="广州"
          p:phone="123567889"/>
</beans>
package com.study.bean.lifecycle;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@Slf4j
public class BeanLifeCycle {
    public static void main(String[] args) {
        log.info("现在开端初始化容器");
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        log.info("容器初始化成功");
        Person person = applicationContext.getBean("person", Person.class);
        log.info("Person:{}", person);
        log.info("现在开端封闭容器");
    }
}

输出:

22:57:32.168 [main] INFO com.study.bean.lifecycle.BeanLifeCycle - 现在开端初始化容器
22:57:32.586 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7f9a81e8
22:57:33.594 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/Users/wanghaifeng/IdeaProjects/study-java/target/classes/com/study/bean/lifecycle/MyBeanFactoryPostProcessor.class]
22:57:33.595 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/Users/wanghaifeng/IdeaProjects/study-java/target/classes/com/study/bean/lifecycle/MyBeanPostProcessor.class]
22:57:33.596 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [/Users/wanghaifeng/IdeaProjects/study-java/target/classes/com/study/bean/lifecycle/MyInstantiationAwareBeanPostProcessor.class]
22:57:33.682 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 9 bean definitions from class path resource [beans.xml]
22:57:33.754 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
22:57:33.984 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myBeanFactoryPostProcessor'
22:57:33.989 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
22:57:33.991 [main] INFO com.study.bean.lifecycle.MyBeanFactoryPostProcessor - 调用BeanFactoryPostProcessor#postProcessBeanFactory
22:57:33.993 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
22:57:34.010 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
22:57:34.016 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
22:57:34.027 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myBeanPostProcessor'
22:57:34.122 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myInstantiationAwareBeanPostProcessor'
22:57:34.157 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'person'
22:57:34.158 [main] INFO com.study.bean.lifecycle.MyInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessorAdapter调用postProcessBeforeInstantiation办法,beanClass:com.study.bean.lifecycle.Person,beanName:person
22:57:34.174 [main] INFO com.study.bean.lifecycle.Person - 【结构器】调用Person的结构器实例化
22:57:34.184 [main] INFO com.study.bean.lifecycle.MyInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessorAdapter调用postProcessAfterInstantiation办法,bean:Person(name=null, address=null, phone=null, beanFactory=null, beanName=null),beanName:person
22:57:34.612 [main] INFO com.study.bean.lifecycle.MyInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessorAdapter调用postProcessProperties办法,pvs:[{"converted":false,"name":"address","optional":false,"originalPropertyValue":{"$ref":"@"},"value":"广州"},{"converted":false,"name":"name","optional":false,"originalPropertyValue":{"$ref":"@"},"value":"张三"},{"converted":false,"name":"phone","optional":false,"originalPropertyValue":{"$ref":"@"},"value":"110"}]
22:57:34.752 [main] INFO com.study.bean.lifecycle.Person - [注入特点]address:广州
22:57:34.752 [main] INFO com.study.bean.lifecycle.Person - [注入特点]name:张三
22:57:34.753 [main] INFO com.study.bean.lifecycle.Person - 【注入特点】phone:110
22:57:34.753 [main] INFO com.study.bean.lifecycle.Person - 【BeanNameAware接口】调用setBeanName办法,name:person
22:57:34.753 [main] INFO com.study.bean.lifecycle.Person - 【BeanFactoryAware接口】调用setBeanFactory办法,beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory
22:57:34.753 [main] INFO com.study.bean.lifecycle.MyBeanPostProcessor - BeanPostProcessor接口调用postProcessBeforeInitialization
22:57:34.753 [main] INFO com.study.bean.lifecycle.MyInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessorAdapter调用postProcessBeforeInitialization办法
22:57:34.753 [main] INFO com.study.bean.lifecycle.Person - 调用@PostConstruct注解的办法
22:57:34.753 [main] INFO com.study.bean.lifecycle.Person - 【InitializingBean接口】调用afterPropertiesSet办法
22:57:34.755 [main] INFO com.study.bean.lifecycle.Person - 【init-method】调用<bean>的init-method特点指定的初始化办法
22:57:34.756 [main] INFO com.study.bean.lifecycle.MyBeanPostProcessor - BeanPostProcessor接口调用postProcessAfterInitialization
22:57:34.756 [main] INFO com.study.bean.lifecycle.MyInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessorAdapter调用postProcessAfterInitialization
22:57:34.813 [main] INFO com.study.bean.lifecycle.BeanLifeCycle - 容器初始化成功
22:57:34.815 [main] INFO com.study.bean.lifecycle.BeanLifeCycle - Person:Person(name=张三, address=广州, phone=110, beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@2805c96b: defining beans [myBeanFactoryPostProcessor,myBeanPostProcessor,myInstantiationAwareBeanPostProcessor,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,person]; root of factory hierarchy, beanName=person)
22:57:34.816 [main] INFO com.study.bean.lifecycle.BeanLifeCycle - 现在开端封闭容器
22:57:34.817 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@7f9a81e8, started on Sat Apr 15 22:57:32 CST 2023
22:57:34.820 [main] INFO com.study.bean.lifecycle.Person - 调用@PreDestroy注解的办法
22:57:34.820 [main] INFO com.study.bean.lifecycle.Person - 【DiposibleBean接口】调用destory办法
22:57:34.820 [main] INFO com.study.bean.lifecycle.Person - 【destory-method】调用<bean>的destroy-method特点指定的初始化办法

图解

Spring Bean生命周期详解和应用(上)

  1. BeanFactoryPostProcessor#postProcessBeanFactory:在Bean被实例化之前,答应覆盖或者增加特点。比如这儿对特点phone的从头赋值为110。

  2. InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation:在实例化方针bean之前履行,假如返回不为null那返回的就是署理bean,能够有效的按捺target bean的默认实例化。

  3. 履行Person的结构器

  4. InstantiationAwareBeanPostProcessor#postAfterInstantiation:在bean被实例化后,在Spring特点填充之前,履行自定义字段注入。假如返回true特点正常填充,返回false跳过特点填充还将阻挠在bean实例上调用任何后续的InstantiationAwareBeanPostProcessor实例

  5. InstantiationAwareBeanPostProcessor#postProcessProperties:在工厂将给定的特点运用于给定的bean之前对其进行后处理。

  6. 对Person的特点进行set

  7. BeanNameAware#setBeanName:给创立的bean设置在bean工厂中的bean name。

  8. BeanFactoryAware#setBeanFactory:将拥有的工厂提供给bean实例的回调。

  9. BeanPostProcessor#postProcessBeforeIntialization:在bean初始化之前,可能是个署理的bean。

  10. InstantiationAwareBeanPostProcessor#postProcessorBeforeInitialization:在bean初始化之前,可能是个署理的bean。

  11. @PostConstruct:此刻bean依赖现已注入完结,能够用该注解注释的办法进行任何初始化。

  12. InitializingBen#afterProperitesSet:所有bean特点都被设置,能够用于履行全体装备校验和终究初始化

  13. init-method指定的办法:作为@PostConstruct和IntializingBean#afterProperitiesSet的替代方案。

  14. BeanPostProcessor#postProcessAfterInitialization:实例化后由BeanFactory或BeanFactory创立的方针调用

  15. InstantiationAwareBeanProcessor#postProcessAfterInitialization:实例化后由BeanFactory或BeanFactory创立的方针调用

  16. @PreDestory注释的办法

  17. DispoableBean#destory

  18. destory-method指定的办法

能够大概分为十个阶段:

  1. 履行结构器进行实例化之前的干涉:BeanFactoryPostProcessor#postProcessBeanFactory、InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
  2. 履行结构器进行实例化
  3. 实例化之后在set特点之前的干涉:InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation、InstantuationAwareBeanPostProcessor#postProcessProperties
  4. 进行set特点
  5. set特点后设置beanName(BeanNameAware#setBeanName)、接收到BeanFactory的回调(BeanFactoryAware#setBeanFactory)
  6. 初始化之前的干涉:BeanPostProcessor#postBeforeInitialization、InstantionAwareBeanPostProcessor#postProcessBeforeInitialization
  7. 进行初始化:@PostConstruct、InitializingBean#afterPropertiesSet、init-method
  8. 实例化之后的干涉:BeanPostProcessor#postProcessAfterInitialization、InstantionAwareBeanPostProcessor#postProcessAfterInitialization
  9. 毁掉前的干涉:@preDestory
  10. 容器封闭时履行毁掉:DisposableBean#destroy、destory-method

分为四大阶段,环绕它们进行干涉:

  1. 实例化(Instantiation)
  2. 特点赋值(Populate)
  3. 初始化(Instialization)
  4. 毁掉(Destruction)

本文正在参加「金石计划」