Spring Bean生命周期详解和应用(上)
前言
写《apollo更改配置刷新@ConfigurationProperties配置类》文章时发现触及到了spring bean生命周期相关知识,这是一个很好的契机去全面温故下它,之前也写过《spring 生命周期最详解》至目前为止有幸被阅览6w+次、200个小伙伴收藏,但是现在看来有些粗糙,想借此进一步巩固下。
基本的思路是:
- 整体有个概念的了解
- 对总体生命周期有个初步的感知
- 重新梳理下生命周期
- 结合源码进一步了解
- 主要看看扩展点
- 实际应用的举例
希望此次能更加通俗易懂、方便记忆。
了解整体
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属性指定的初始化方法
图解
-
BeanFactoryPostProcessor#postProcessBeanFactory:在Bean被实例化之前,允许覆盖或者添加属性。比如这里对属性phone的重新赋值为110。
-
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation:在实例化目标bean之前执行,如果返回不为null那返回的就是代理bean,可以有效的抑制target bean的默认实例化。
-
执行Person的构造器
-
InstantiationAwareBeanPostProcessor#postAfterInstantiation:在bean被实例化后,在Spring属性填充之前,执行自定义字段注入。如果返回true属性正常填充,返回false跳过属性填充还将阻止在bean实例上调用任何后续的InstantiationAwareBeanPostProcessor实例
-
InstantiationAwareBeanPostProcessor#postProcessProperties:在工厂将给定的属性应用于给定的bean之前对其进行后处理。
-
对Person的属性进行set
-
BeanNameAware#setBeanName:给创建的bean设置在bean工厂中的bean name。
-
BeanFactoryAware#setBeanFactory:将拥有的工厂提供给bean实例的回调。
-
BeanPostProcessor#postProcessBeforeIntialization:在bean初始化之前,可能是个代理的bean。
-
InstantiationAwareBeanPostProcessor#postProcessorBeforeInitialization:在bean初始化之前,可能是个代理的bean。
-
@PostConstruct:此时bean依赖已经注入完成,可以用该注解注释的方法进行任何初始化。
-
InitializingBen#afterProperitesSet:所有bean属性都被设置,可以用于执行总体配置校验和最终初始化
-
init-method指定的方法:作为@PostConstruct和IntializingBean#afterProperitiesSet的替代方案。
-
BeanPostProcessor#postProcessAfterInitialization:实例化后由BeanFactory或BeanFactory创建的对象调用
-
InstantiationAwareBeanProcessor#postProcessAfterInitialization:实例化后由BeanFactory或BeanFactory创建的对象调用
-
@PreDestory注释的方法
-
DispoableBean#destory
-
destory-method指定的方法
可以大概分为十个阶段:
- 执行构造器进行实例化之前的干预:BeanFactoryPostProcessor#postProcessBeanFactory、InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
- 执行构造器进行实例化
- 实例化之后在set属性之前的干预:InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation、InstantuationAwareBeanPostProcessor#postProcessProperties
- 进行set属性
- set属性后设置beanName(BeanNameAware#setBeanName)、接收到BeanFactory的回调(BeanFactoryAware#setBeanFactory)
- 初始化之前的干预:BeanPostProcessor#postBeforeInitialization、InstantionAwareBeanPostProcessor#postProcessBeforeInitialization
- 进行初始化:@PostConstruct、InitializingBean#afterPropertiesSet、init-method
- 实例化之后的干预:BeanPostProcessor#postProcessAfterInitialization、InstantionAwareBeanPostProcessor#postProcessAfterInitialization
- 销毁前的干预:@preDestory
- 容器关闭时执行销毁:DisposableBean#destroy、destory-method
分为四大阶段,围绕它们进行干预:
- 实例化(Instantiation)
- 属性赋值(Populate)
- 初始化(Instialization)
- 销毁(Destruction)
转载自:https://juejin.cn/post/7222075996065579045