当前位置: 首页 > news >正文

Spring Bean生命周期执行流程详解

文章目录

  • 一、什么是Spring Bean生命周期?
  • 工作流程图:
  • 二、Bean生命周期执行流程验证
    • 1.编写测试代码验证结果
    • 2.源码追溯Bean初始化回调过程


一、什么是Spring Bean生命周期?

Spring Bean生命周期是指从Bean的创建到销毁的整个过程,其中涉及到Spring容器对Bean的一系列处理操作,包对Bean的实例化、依赖注入、初始化和销毁。Spring框架中Bean的生命周期主要包括以下关键步骤:

  1. 实例化BeanSpring容器根据Bean的定义从容器中取出Bean的类,通过反射机制进行实例化。
  2. 属性填充:Spring容器从Bean定义中获取属性值,将这些属性值注入到新创建的Bean实例中,这个过程也叫做依赖注入。
  3. Aware接口回调:如果Bean涉及到实现了BeanNameAwareBeanClassLoaderAwareBeanFactoryAware接口,则会触发BeanNameAware.setBeanNameBeanClassLoaderAware.setBeanClassLoaderBeanFactory.setBeanFactory方法的调用。
  4. BeanPostProcessor接口回调:触发前置方法BeanPostProcessor.postProcessBeforeInitialization。注意的是ApplicationContextAwareProcessorInitDestroyAnnotationBeanPostProcessor都是BeanPostProcessor的实现类,因此可能触发ApplicationContextAwaresetApplicationContext方法回调和init-Method回调。
  5. InitializingBean接口回调:触发InitializingBean.afterPropertiesSet方法。
  6. BeanPostPorcessor接口回调:触发后置方法BeanPostProcessor.postProcessAfterInitialization方法。
  7. Bean初始化完成,可以投入使用
  8. Bean实现了DisposableBean接口时,Spring容器关闭时,会回调DisposableBean.destory方法。
  9. Bean被销毁,生命周期结束。

工作流程图:

在这里插入图片描述


二、Bean生命周期执行流程验证

1.编写测试代码验证结果

定义一个LifeCycleBean类,将其作为SpringBean进行管理,让其实现BeanNameAware, BeanFactoryAware, BeanPostProcessor, ApplicationContextAware, InitializingBean, DisposableBean接口,在实现方法中打印对应的信息,查看方法调用的顺序。


import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;

@Component
public class LifeCycleBean implements BeanNameAware, BeanFactoryAware, BeanPostProcessor, ApplicationContextAware, InitializingBean, DisposableBean {

    //前置处理是否被调用标识
    private volatile boolean beforeInitializationInvoked = false;
    //后置处理是否被调用标识
    private volatile boolean afterInitializationInvoked = false;

    @Override
    public void setBeanName(String name) {
        System.out.println("BeanNameAware.name be invoked");
    }

    @PostConstruct
    public void init() {
        System.out.println("PostConstruct.init be invoked");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean.destroy be invoked");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean.afterPropertiesSet be invoked");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware.setApplicationContext be invoked");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!beforeInitializationInvoked) {
            beforeInitializationInvoked = true;
            System.out.println("BeanPostProcessor.postProcessBeforeInitialization be invoked");
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (!afterInitializationInvoked) {
            afterInitializationInvoked = true;
            System.out.println("BeanPostProcessor.postProcessAfterInitialization be invoked");
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware.setBeanFactory be invoked");
    }
}

启动项目,查看控制台打印结果如下:
在这里插入图片描述
关闭容器后,控制台打印如下:
在这里插入图片描述
因此可以得出,Bean启动后,初始化的执行顺序是:BeanNameAware->BeanFactoryAware->ApplicationContextAware(由ApplicationContextAwareProcessor调用)->PostConstruct(由InitDestroyAnnotationBeanPostProcessor调用)->BeanPostProcessor.postProcessBeforeInitialization(自定义)->InitializingBean.afterPropertiesSet->BeanPostProcessor.postProcessAfterInitialization–>DisposableBean.destory


2.源码追溯Bean初始化回调过程

通过断点可以得出Bean初始化的入口在AbstractAutowireCapableBeanFactory.initializeBean方法。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

其中的一个方法invokeAwareMethods的命名十分明显,用于调用一些Aware接口的实现类,进入invokeAwareMethods方法后,通过判断当前bean是否为Aware类型,如果是则进一步判断是Aware接口下的哪一种类型,然后进行类型转换调用对应的方法。

	private void invokeAwareMethods(String beanName, Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

执行完invokeAwareMethods后,则调用initializeBean方法中的applyBeanPostProcessorsBeforeInitialization方法,通过遍历现有的BeanPostProcessor类,依次调用其postProcessBeforeInitialization方法。

	@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

其中重点关注ApplicationContextAwareProcessorInitDestroyAnnotationBeanPostProcessor两个类,他们都属于BeanPostPorcessor的实现类,因此在循环时都会调用其postProcessBeforeInitialization方法。ApplicationContextAwareProcessor.postProcessBeforeInitialization方法中有一个比较重要的方法invokeAwareInterfaces,该方法也是用于回调一些实现了Aware接口的类。其中ApplicationContextAware.setApplicationContext就是在此处被调用,当然还涉及到EnvironmentAwareEmbeddedValueResolverAwareMessageSourceAware等的回调。

	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 ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}

InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization方法重要是通过反射机制调用被注释PostConstruct修饰的init-Method.

在完成applyBeanPostProcessorsBeforeInitialization调用后,则会调用invokeInitMethods方法, 如果Bean实现了InitializingBean接口,Spring容器会调用其afterPropertiesSet()方法。

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

最调用applyBeanPostProcessorsAfterInitialization方法,通过遍历BeanPostProcessor的实现类,调用其postProcessAfterInitialization后置方法。

	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

相关文章:

  • 对Android中zygote的理解
  • 安装OpenJDK1.8 17 (macos M芯片)
  • Qt 入门 3 之对话框 QDialog
  • 前端性能优化实战:从 Webpack 到 Vite 的全栈提速方案
  • 解锁 MCP:模型上下文协议的介绍与应用​,技术解析与应用场景
  • 顶刊【遥感目标检测】【TGRS】LSKF-YOLO:面向高分辨率卫星遥感影像电力塔检测的大规模选择性核特征融合网络
  • LeetCode hot 100—编辑距离
  • 记录一下学习docker的命令(不断补充中)
  • 微信小程序跳
  • oracle json笔记
  • 线程同步与互斥(下)
  • 关于 Spring Boot + Vue 前后端开发的打包、测试、监控、预先编译和容器部署 的详细说明,涵盖从开发到生产部署的全流程
  • spring 依赖注入的好处
  • vscode远程连接树莓派报错> Host key verification failed.> 过程试图写入的管道不存在。
  • mysql-innodb_autoinc_lock_mode=2 和innodb_autoinc_lock_mode=1可能引发的问题
  • CISP-PTE WEB题通关记录
  • 基于Kubeadm实现K8S集群扩缩容指南
  • 第十一届 蓝桥杯 嵌入式 省赛
  • cache更新策略
  • Redis Java 客户端 之 Jedis
  • 国内知名网站建设企业/搜索引擎优化是指什么意思
  • 做站群网站好优化吗/新手怎么做seo优化
  • 淘宝实时优惠券网站怎么做的/常州seo外包
  • 盗号和做钓鱼网站那个罪严重/百度网址大全 旧版本
  • 阿里云网站建设基本流程/线上网络平台推广
  • 公司电脑做网站/2021百度热搜年度榜