Spring Bean 的生命周期基本流程
一个Spring的Bean从出生到销毁的全过程就是他的整个生命周期,
整个生命周期可以大致分为3个大的阶段 :
-
创建
-
使用
-
销毁
还可以分为5个小步骤 :
实例化(Bean的创建) , 初始化赋值, 注册Destruction回调 , Bean的正常使用 以及 Bean的销毁
Bean的创建和初始化赋值是分开的
具体代码实现 :
Spring容器在进行实例化的时候,会将xml配置的< bean > 的信息封装成一个BeanDefinition对象, Spring根据BeanDefinition来创建Bean对象,里面有很多的属性来描述Bean
-
beanClassName : bean的类名
-
initMethodName : 初始化方法名称
-
properryValues : bean的属性值
-
scope : 作用域
-
lazyInit : 延迟初始化
-
实例化Bean(实例化阶段)
-
Spring容器首先创建Bean实例
-
调用Bean的构造函数,来实例化Bean对象
-
Spring在这一步创建Bean实例。 主要代码在AbstractAutowireCapableBeanFactory类中的createBeanInstance方法中实现
就是先确保这个Bean对应的类已经被加载,然后确保他是public的,然后如果有工厂方法,则直接调用工厂方法创建Bean,如果没有的话就调用它的构造方法来创建这个Bean.
这里需要注意的是 ,在Spring的完整Bean创建和初始化流程中,容器会在调用createBeanInstance之前检查Bean定义的作用域。如果是Singleton,容器会在其内部单例缓存中查找现有实例。如果实例已经存在,他将被重用;如果不存在,才会调用createBeanInstance来创建新的实例;
-
-
-
(依赖注入)设置属性值(初始化阶段)
-
Spring容器注入必要的属性到Bean中
- populateBean方法是Spring Bean生命周期中的一个关键部分,负责将属性值应用到新创建的Bean实例。他处理了自动装配,属性注入,依赖检查等多个方面 . 就是把各种属性进行初始化
-
-
检查Aware
-
如果Bean实现了BeanNameAware , BeanClassLoaderAware等这些Aware接口, Spring容器会调用它们
-
BeanNameAware :通过这个接口,Bean可以获取到自己在Spring容器中的名字。这对于需要根据Bean的名称某些操作的常见很有用
-
ApplicationContextAware: 获取ApplicationContext对象;
-
BeanFactoryAware : 通过这个接口可以获取对BeanFactory的引用,获得对BeanFactory的访问权限
-
-
-
调用BeanPostProcessor前置处理方法 (初始化之前进行回调)
- 在Bean初始化之前, 允许自定义的BeanPostProcessor对Bean实例进行处理,如修改Bean的状态. BeanPostProcessor的postProcessBeforeInitialization方法会在此时被调用
-
执行初始化方法
-
调用InitializingBean的afterPropertiesSet方法
-
提供一个机会, 在所有Bean属性设置完成后进行初始化操作, 如果Bean实现了InitializingBean接口, afterPropertiesSet方法会被调用
-
主要作用就是帮助我们在Bean的初始化前添加一些自己的逻辑处理,Spring内置了很多BeanPostProcessor,我们也可以定义一个或者多个BeanPostProcessor接口的实现,然后注册到容器中;
-
-
调用自定义init-method方法(初始化方法)
- 提供一种配置方式, 在xml配置中指定Bean的初始化方法. 如果Bean在配置文件中定义了初始化方法,那么该方法就会被调用
-
-
调用BeanPostProcessor的后置处理方法 (Spring中对类进行增强的时候(AOP),就会使用后置处理器) --> AOP底层使用了动态代理和CGLB动态代理
- 在Bean初始化之后,再次允许BeanPostProcessor对Bean进行处理. BeanPostProcessor的postProcessAfterInitialization方法会在此时被调用
-
注册Destruction回调
- 如果Bean实现了DIsposableBean接口或者bean定义中指定了自定义的销毁方法 ,Spring容器会为这些Bean注册一个销毁回调,确保在容器关闭的时候能够正确的清理资源
-
Bean准备就绪(Bean的使用阶段)
- 此时,Bean已经完全初始化,可以开始处理应用程序的请求了
-
调用DisposableBean的destroy方法(Bean的销毁阶段)
-
当容器关闭的时候, 如果Bean实现了DisposableBean接口, destroy方法会被调用
-
在DisposableBeanAdapter的destroy方法中实现
-
-
调用自定义的destroy-method当容器要进行关闭的时候,对象就会进入销毁阶段 ,最典型的就是,如果你使用了@PreDestroy注解,这个方法就是销毁方法 , Spring容器关闭的时候就会调用这个自定义的销毁方法
-
如果Bean在配置文件中定义了销毁方法, 那么该方法就会被调用
-
在DisposableBeanAdapter的destroy方法中实现
-
可以看到, 整个Bean的创建的过程都依赖于AbstractAutowireCapableBeanFactory这个类,而销毁主要依赖于DisposableBeanAdapter这个类
代码实践
java
package com.sfx.spring6;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
* Created with IntelliJ IDEA.
* Description:
* User: sfx
* Date: 2024-02-20
* Time: 21:20
*/
public class CatDog implements BeanNameAware, InitializingBean, DisposableBean {
private String name;
public CatDog() {
System.out.println("1. 实例化Bean");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("2. 执行了set方法, 设置相关属性");
this.name = name;
}
public void myInit() {
System.out.println("6. 执行了自定义初始化方法");
}
public void myDestroy() {
System.out.println("10. 执行了自定义的销毁方法");
}
@Override
public void setBeanName(String name) {
System.out.println("3. 执行了 BeanNameAware");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("5. 执行afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("9. 执行了DisposableBean");
}
}
java
package com.sfx.spring6;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
* Created with IntelliJ IDEA.
* Description:
* User: sfx
* Date: 2024-02-20
* Time: 21:20
*/
public class CatDog implements BeanNameAware, InitializingBean, DisposableBean {
private String name;
public CatDog() {
System.out.println("1. 实例化Bean");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("2. 执行了set方法, 设置相关属性");
this.name = name;
}
public void myInit() {
System.out.println("6. 执行了自定义初始化方法");
}
public void myDestroy() {
System.out.println("10. 执行了自定义的销毁方法");
}
@Override
public void setBeanName(String name) {
System.out.println("3. 执行了 BeanNameAware");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("5. 执行afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("9. 执行了DisposableBean");
}
}
java
package com.sfx.spring6;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created with IntelliJ IDEA.
* Description:
* User: sfx
* Date: 2024-02-20
* Time: 21:23
*/
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
CatDog bean = applicationContext.getBean(CatDog.class);
String name = bean.getName();
System.out.println("8. 使用了Bean , " + name);
((ClassPathXmlApplicationContext) applicationContext).close();
}
}
XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 在spring中创建对象 -->
<!-- 配置 dog 这个Bean-->
<bean id = "catDog" class="com.sfx.spring6.CatDog" init-method="myInit" destroy-method="myDestroy">
<property name="name" value="张三"></property>
</bean>
<bean id="processor" class="com.sfx.spring6.Processor">
</bean>
</beans>
项目中会用到哪些流程呢 ?
我们在项目中一般等到项目初始化完成后立马执行一些动作, 比如RocketMQ开启消费者,还有等等我们需要在项目初始化完成之后就要执行一些动作,我们就可以调用 InitializingBean 的afterPropertiesSet方法
好的记忆方法
我们可以给面试官这么讲解, SpringBean的生命周期分为三个大的阶段
- 创建
- 使用
- 销毁
如果划分为具体的细的5个阶段 :
- 实例化
- 初始化(依赖注入)
- 注册Destruction的回调
- Bean的使用
- Bean的销毁
然后我们再来了解每一个阶段都要做哪些事情
- 实例化
- 首先会根据扫描我们写的xml,将一些属性设置到BeanDefination对象上,然后调用构造方法创建出一个Bean
- 初始化
-
给Bean设置属性(此时会调用bean的set方法)
-
检查有没有实现以aware结尾的相关接口
-
BeanNameAware :通过这个接口,Bean可以获取到自己在Spring容器中的名字。这对于需要根据Bean的名称某些操作的常见很有用
-
ApplicationContextAware: 获取ApplicationContext对象;
-
BeanFactoryAware : 通过这个接口可以获取对BeanFactory的引用,获得对BeanFactory的访问权限
-
-
执行初始化前置方法
-
执行初始化方法 (有两个, 首先先会调用 InitializingBean 的afterPropertiesSet方法,然后会调用自己定义的初始化方法)
-
执行初始化后置方法
-
注册Destruction的回调
- 如果Bean实现了DIsposableBean接口或者bean定义中指定了自定义的销毁方法 ,Spring容器会为这些Bean注册一个销毁回调,确保在容器关闭的时候能够正确的清理资源
-
开始使用Bean
-
调用DisposableBean的destroy方法**(Bean的销毁阶段)**
-
当容器关闭的时候, 如果Bean实现了DisposableBean接口, destroy方法会被调用
-
在DisposableBeanAdapter的destroy方法中实现
-
-
调用自定义的destroy-method 当容器要进行关闭的时候,对象就会进入销毁阶段 ,最典型的就是,如果你使用了@PreDestroy注解(对于SpringBoot),这个方法就是销毁方法 , Spring容器关闭的时候就会调用这个自定义的销毁方法
-
如果Bean在配置文件中定义了销毁方法, 那么该方法就会被调用
-
在DisposableBeanAdapter的destroy方法中实现
-
-
对于SpringBoot而言,如果你想要在实例化和依赖注入完成后进行初始化操作,可以加@PostConstruct注解 ,当然也可以使用 InitializingBean 的afterPropertiesSet方法
如果你想要自定义销毁方法 , 可以加 @PreDestroy注解
下次分享再见~~~