☀️从源码的角度梳理SpringBean的生命周期~✨
前言
⚡️ 本篇结合Spring源码简要的梳理了一下Spring的bean的生命周期,注释已经写在自己拉下来的Spring项目里面啦,如果感兴趣的小伙伴,可以从本人的 GitHub【Spring-Framework-Cocowwy】 仓库里面下载源码观摩噢~
Spring源码相关系列文章:
⭐️ 【Spring源码学习篇(一)】☀️Spring5本地环境编译,超级实用!!✨
Bean的生命周期
⚡️ 在通过源码进行分析之前,先上代码和Demo,简要看看Bean的生命周期有关的几个接口的使用,先实操再上硬菜!🍜
Bean的生命周期简介
⚡️ 简简单单总结一下叭:一个JavaBean,从实例化然后经过属性赋值再到初始化完成最后再到销毁的过程,就是其生命周期,在一个bean经过这个生命周期的过程中,Spring提供了许多的可扩展点,用于我们对其进行扩展。类似于下图。
这几个接口你了解吗?
对于Bean的生命周期而言,Spring为其提供了如下几个重要的接口:
⚡️ InstantiationAwareBeanPostProcessor
⚡️ BeanPostProcessor
⚡️ XXXXXXAware
⭐️ 接下来本篇文章就针对这三个核心接口来展SpringBean的生命周期我们可以从下图来看SpringBean的生命过程中以上接口各自是在什么情况下执行的。
🌚图画的有点丑,见谅🌚
⭐️由上图可以知道,在 实例化 的前后,会分别执行 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation / postProcessAfterInstantiation 在初始化之前会执行一系列的 XXXAware接口 ,在执行完这些接口之后同时在 初始化 前后会执行BeanPostProcessor#postProcessBeforeInstantiation / postProcessAfterInstantiation ,最后再到Bean的销毁。到此Bean的生命周期中几个重要的可扩展的接口就已经走完。
⚡️ 细心的读者会发现InstantiationAwareBeanPostProcessor是继承自BeanPostProcessor的。
InstantiationAwareBeanPostProcessor
🌝 感知Bean实例化的处理器,继承自 BeanPostProcessor ,在bean实例化的前后执行
BeanPostProcessor
🌝 检查标记接口或使用代理包装 bean,在初始化的前后执行
XXXXAware
🌝 继承自 Aware 接口,bean对象继承该接口后,能够在初始化bean之前从该接口方法中拿到xxx的一些相关属性,并且执行该方法
挽起袖子,撸源码
前期准备工作
⚡️ 先放上调试的Demo
💥 Student
/**
* @author Cocowwy
* @create 2021-08-08-13:38
*/
public class Student implements BeanNameAware, EnvironmentAware {
private String name;
private String studentNo;
private String sex;
public Student() {}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", studentNo='" + studentNo + '\'' +
", sex='" + sex + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("对name属性进行赋值");
this.name = name;
}
public String getStudentNo() {
return studentNo;
}
public void setStudentNo(String studentNo) {
System.out.println("对studentNo属性进行赋值");
this.studentNo = studentNo;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
System.out.println("对sex属性进行赋值");
this.sex = sex;
}
@Override
public void setBeanName(String name) {
System.out.println("执行Student类的BeanNameAware接口方法");
}
@Override
public void setEnvironment(Environment environment) {
System.out.println("执行Student类的EnvironmentAware接口方法");
}
}
💥 MyBeanPostProcessor
/**
* @author Cocowwy
* @create 2021-08-08-15:10
*/
public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "执行初始化之前的方法【BeanPostProcessor#postProcessBeforeInitialization】");
// 从源码可以知道这里就算返回null spring底层还是能够取到bean对象
// AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "执行初始化之后的方法【BeanPostProcessor#postProcessAfterInitialization】");
Student returnBean = (Student) bean;
returnBean.setName("BeanPostProcessor#postProcessAfterInitialization");
return returnBean;
}
// BeanPostProcessor 的执行顺序
@Override
public int getOrder() {
return 0;
}
}
💥 MyInstantiationAwareBeanPostProcessor
/**
* @author Cocowwy
* @create 2021-08-08-15:07
*/
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor , Ordered {
/**
* 对象实例化之前调用,返回回值是Object类型
* 由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成对象的目标对象的实例(比如代理对象)。
* 如果该方法的返回值代替原本该生成的目标对象,
* 后续只有postProcessAfterInstantiation方法会调用,其他方法不调用;否则按照正常的流程走
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println(beanName + "执行实例化之前的方法【InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation】");
return null;
}
/**
* 对象实例化之后调用,此时对象的属性值都是null。
* 返回值是决定要不要调用postProcessPropertyValues方法中的一个因素(因为还有一个因素是mbd.getDependencyCheck());
* 如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会不执行;
* 如果返回true,postProcessPropertyValues就会被执行
* @param bean the bean instance created, with properties not having been set yet
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "执行实例化之后的方法【InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation】");
return true;
}
@Override
public int getOrder() {
return 0;
}
}
💥 spring.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="bean.Student">
<property name="name" value="Cocowwy"></property>
<property name="sex" value="boy"></property>
<property name="studentNo" value="PC66715"></property>
</bean>
<bean class="life.MyBeanPostProcessor"/>
<bean class="life.MyInstantiationAwareBeanPostProcessor"/>
💥 Test
/**
* @author Cocowwy
* @create 2021-08-08-17:28
*/
public class Test {
public static void main(String[] args) {
System.out.println("=====================spring容器【create by:Cocowwy】==================================");
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Student student = (Student) context.getBean("student");
System.out.println(student);
}
}
InstantiationAwareBeanPostProcessor的执行时机
postProcessBeforeInstantiation
🍉 方法的执行入口:AbstractAutowireCapableBeanFactory#createBean
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
🍉 点击 resolveBeforeInstantiation 进去瞅瞅源码~
/**
* 【应用实例化前的后处理器】
*/
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 确保此时真正解析了 bean 类
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 执行 applyBeanPostProcessorsBeforeInstantiation 的时机
// student执行实例化之前的方法【InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation】
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
🍉 该方法在 Object beanInstance = doCreateBean(beanName, mbdToUse, args)
之前执行,即bean初始化之前执行
postProcessAfterInstantiation
🍉 该方法是在实例化之后执行,从上文 Object beanInstance = doCreateBean(beanName, mbdToUse, args)
接着往后走,在这个方法里完成了bean的初始化和实例化,故此我们先从这里点进去接着看源码~
进入到方法里面,看到我们的 populateBean(beanName, mbd, instanceWrapper)
方法,在这里完成属性的赋值。
接着从这里点进去,进入到我们的 populateBean 方法,
🍉 方法的执行入口:AbstractAutowireCapableBeanFactory#populateBean,接下来贴出该方法里执行postProcessAfterInstantiation的位置
// InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 执行 postProcessAfterInstantiation
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
🍉 由下图截屏可以得知,bean仅完成了实例化,但是未进行属性赋值(student全部为空)的操作,在该代码块的位置进行了实例化的后置处理器的postProcessAfterInstantiation操作
XXXXAware接口的执行时机
🍉 刚才从populateBean里面执行完了实例化的后置处理器,以及实例化后的属性赋值,接下来开始执行的是XXXXAware接口的调用了
🍉 坐标定位:AbstractAutowireCapableBeanFactory#doCreateBean
try {
//这里是拿的包装了这个bean的包装类BeanWrapper,在这里完成了对属性的赋值
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean 这里执行了bean的Aware接口的方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
......
}
🍉 接着我们点进initializeBean开始跟源码~
🍉 坐标定位:AbstractAutowireCapableBeanFactory#initializeBean
// 当运行未知的Java程序的时候,该程序可能有恶意代码(删除系统文件、重启系统等),
// 为了防止运行恶意代码对系统产生影响,需要对运行的代码的权限进行控制,这时候就要启用Java安全管理器。
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
// 未启用安全管理器就执行这三个接口【BeanNameAware BeanClassLoaderAware BeanFactoryAware】
// 执行Student类的BeanNameAware接口方法,获取到的beanName为:student
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 执行其余的Aware接口方法 在初始化之前执行bean的处理器
// 执行如下接口处理【EnvironmentAware EmbeddedValueResolverAware ResourceLoaderAware ApplicationEventPublisherAware
// MessageSourceAware ApplicationContextAware ApplicationStartupAware】
// student执行初始化之前的方法【BeanPostProcessor#postProcessBeforeInitialization】
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
🍉 虽然上面巴拉巴拉的一大堆,不过执行Aware接口地方的代码就两个部分,一个是 invokeAwareMethods(beanName, bean)
另外一个是 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
BeanNameAware / BeanClassLoaderAware / BeanFactoryAware
🍉 第一个部分
我们可以先点进去 invokeAwareMethods看看里面的内容
// 调用invoke方法
private void invokeAwareMethods(String beanName, Object bean) {
// 这一块用来debug的时候打印的哈~
if (beanName.equals("student")) {
System.out.println("执行【BeanNameAware接口】part:1======【AbstractAutowireCapableBeanFactory:invokeAwareMethods】");
}
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
// 将beanName返回
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
// 拿到类加载器,如果不为空则返回该类加载器
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
// 返回Bean工厂 ----》 AbstractAutowireCapableBeanFactory
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
🍉 可以看到,bean实现了Aware接口的BeanNameAware、BeanClassLoaderAware、BeanFactoryAware其中的接口的时候,会在这一步操作执行该接口的方法,同时拿到一系列bean相关的参数,就比如BeanNameAware,可以在这里拿到bean的name
EnvironmentAware / EmbeddedValueResolverAware / ResourceLoaderAware ApplicationEventPublisherAware / MessageSourceAware / ApplicationContextAware / ApplicationStartupAware
🍉 接着我们再来看看 第二个部分 applyBeanPostProcessorsBeforeInitialization方法
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 剩余的Aware接口在这里进行的解析 -》 ApplicationContextAwareProcessor#postProcessBeforeInitialization
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
🍉 当代码运行到 Object current = processor.postProcessBeforeInitialization(result, beanName)
的时候,执行的是 ApplicationContextAwareProcessor#postProcessBeforeInitialization
方法,接下来贴出这块的核心代码
// 初始化前的处理
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 执行其余的Aware接口 如果bean没实现这些接口就返回
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
......
if (...) {......} else {
// 执行aware接口的方法,这里得if打了个日志哈
if (beanName.equals("student")) {System.out.println("执行【EnvironmentAware接口】part:2======【ApplicationContextAwareProcessor:invokeAwareInterfaces】");}
// 实际执行第二部分的Aware接口
invokeAwareInterfaces(bean);
}
......
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
🍉 最终我们可以看到实际执行XXXAware接口的地方是invokeAwareInterfaces方法,在这里,给bean提供了扩展点,能够在赋值完初始化前获取到environment,applicationContext 等信息
BeanPostProcessor的执行时机
postProcessBeforeInitialization
🍉 如果你在debug源码的时候就会发现,在上文执行Aware接口的时候,代码是长这个鬼样的
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 剩余的Aware接口在这里进行的解析 -》 ApplicationContextAwareProcessor#postProcessBeforeInitialization
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
🍉 计算一下 getBeanPostProcessors()
的值就会发现,这里面有我们自己定义的 MyBeanPostProcessors ,也就是说,在执行完上面的Aware接口的随后(在一个for循环内),紧接着执行了我们的BeanPostProcessor#postProcessBeforeInitialization
postProcessAfterInstantiation
🍉 坐标定位:AbstractAutowireCapableBeanFactory#initializeBean
if (mbd == null || !mbd.isSynthetic()) {
// 执行其余的Aware接口方法 在初始化之前执行bean的处理器
// 执行如下接口处理【EnvironmentAware EmbeddedValueResolverAware ResourceLoaderAware ApplicationEventPublisherAware
// MessageSourceAware ApplicationContextAware ApplicationStartupAware】
// student执行初始化之前的方法【BeanPostProcessor#postProcessBeforeInitialization】
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 初始化
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
// ......
}
if (mbd == null || !mbd.isSynthetic()) {
// 在初始化之前执行bean的处理器 student执行初始化之后的方法【BeanPostProcessor#postProcessAfterInitialization】
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
🍉 从上文可以知道,此时已经执行完aware接口以及postProcessBeforeInitialization,此时接着往下经过了Init初始化完毕之后,开始执行applyBeanPostProcessorsAfterInitialization方法,这里执行的就是我们的BeanPostProcessor的postProcessAfterInstantiation执行的地方了,接着点进源码品尝一番,坐标定位:AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
// 这里可以知道就算返回的是空的,依旧可以拿到bean
if (current == null) {
return result;
}
result = current;
}
return result;
}
🍉 可以看到,此时Object current = processor.postProcessAfterInitialization(result, beanName)
执行了实例化之后的后置处理器,同时有个点我们可以注意一下,这里对current进行了判空的操作,也就是说,我们在这里对bean对象进行自己的操作(比如自己进行赋值等),如果返回的是空,那么就返回原来的bean Demo中就在这里对bean重新进行了赋值操作
Bean出生了
🍉 至此,Bean已经完整的度过了他的生命周期了,历经了实例化,实例化的前后后置处理器,属性赋值,初始化的前后后置处理器,然后形成了一个Bean,看下我们的控制台打印
=====================spring容器【create by:Cocowwy】==================================
student执行实例化之前的方法【InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation】
student执行实例化之后的方法【InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation】
对name属性进行赋值
对sex属性进行赋值
对studentNo属性进行赋值
执行【BeanNameAware接口】part:1======【AbstractAutowireCapableBeanFactory:invokeAwareMethods】
执行Student类的BeanNameAware接口方法
执行【EnvironmentAware接口】part:2======【ApplicationContextAwareProcessor:invokeAwareInterfaces】
执行Student类的EnvironmentAware接口方法
student执行初始化之前的方法【BeanPostProcessor#postProcessBeforeInitialization】
student执行初始化之后的方法【BeanPostProcessor#postProcessAfterInitialization】
对name属性进行赋值
Student{name='BeanPostProcessor#postProcessAfterInitialization', studentNo='PC66715', sex='boy'}
🍉 配置文件中我们设置的BeanName为Cocowwy,但是为什么这里的name为BeanPostProcessor#postProcessAfterInitialization?
❓ 如果上面的文章有认真阅读的话,熟悉了Bean的生命周期的话,那么这种小问题就难不倒你了~
⚡️ 到此,SpringBean生命周期中的几个重要的后置处理器以及Aware接口的流程已经走完 🔚如果有疑问或者有不对的地方欢迎在下方留言!
⭐️如果需要源码的可以上本人的Github【Spring-Framework-Cocowwy】上拉喔~⭐️