【源码解析】Spring Bean生命周期源码解析

news2024/11/18 22:53:43

Spring启动核心

AbstractApplicationContext#refresh,Spring刷新容器的核心方法。最关键的就是

  • AbstractApplicationContext#invokeBeanFactoryPostProcessors,扫描Bean
  • AbstractApplicationContext#finishBeanFactoryInitialization,生成Bean。

    【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析

AbstractAutowireCapableBeanFactory#doCreateBean,Spring生成Bean后会进行初始化。

  • populateBean,属性赋值
  • initializeBean,初始化
【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析
	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		// ...

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		// ...

		return exposedObject;
	}
【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析

在这里插入图片描述

【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析

初始化

AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition),初始化。

  • invokeAwareMethods
  • applyBeanPostProcessorsBeforeInitialization
  • invokeInitMethods
  • applyBeanPostProcessorsAfterInitialization

    【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析
	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;
	}
【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析

触发BeanNameAware等方法

AbstractAutowireCapableBeanFactory#invokeAwareMethods,触发Aware方法,触发BeanNameAwareBeanClassLoaderAwareBeanFactoryAware

【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析

	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);
			}
		}
	}
【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析

触发后置处理器的postProcessBeforeInitialization方法

ApplicationContextAwareProcessor#postProcessBeforeInitializationApplicationContextAwareProcessor是后置处理器,处理额外的Aware重写方法。

	@Override
	@Nullable
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
				bean instanceof ApplicationStartupAware)) {
			return bean;
		}

		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return 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);
		}
	}

InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization,触发@PostConstruct标注的方法。

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
		try {
			metadata.invokeInitMethods(bean, beanName);
		}
		catch (InvocationTargetException ex) {
			throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
		}
		return bean;
	}

InitDestroyAnnotationBeanPostProcessor#findLifecycleMetadata,寻找@PostConstruct@PreDestroy标注的方法。

	private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
		if (this.lifecycleMetadataCache == null) {
			// Happens after deserialization, during destruction...
			return buildLifecycleMetadata(clazz);
		}
		// Quick check on the concurrent map first, with minimal locking.
		LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
		if (metadata == null) {
			synchronized (this.lifecycleMetadataCache) {
				metadata = this.lifecycleMetadataCache.get(clazz);
				if (metadata == null) {
					metadata = buildLifecycleMetadata(clazz);
					this.lifecycleMetadataCache.put(clazz, metadata);
				}
				return metadata;
			}
		}
		return metadata;
	}

	private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
		if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
			return this.emptyLifecycleMetadata;
		}

		List<LifecycleElement> initMethods = new ArrayList<>();
		List<LifecycleElement> destroyMethods = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<LifecycleElement> currInitMethods = new ArrayList<>();
			final List<LifecycleElement> currDestroyMethods = new ArrayList<>();

			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
					LifecycleElement element = new LifecycleElement(method);
					currInitMethods.add(element);
					if (logger.isTraceEnabled()) {
						logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
					}
				}
				if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
					currDestroyMethods.add(new LifecycleElement(method));
					if (logger.isTraceEnabled()) {
						logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
					}
				}
			});

			initMethods.addAll(0, currInitMethods);
			destroyMethods.addAll(currDestroyMethods);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
				new LifecycleMetadata(clazz, initMethods, destroyMethods));
	}
【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析

触发afterPropertiesSet方法

AbstractAutowireCapableBeanFactory#invokeInitMethods,触发实现了InitializingBean的方法。

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

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("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.hasAnyExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}
【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析 【源码解析】Spring Bean生命周期源码解析

触发后置处理器postProcessAfterInitialization方法

AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization,获取后置处理器,执行postProcessAfterInitialization

	@Override
	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;
	}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/585413.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySql】InnoDB一棵B+树可以存放多少行数据?

文章目录 背景一、怎么得到InnoDB主键索引B树的高度&#xff1f;二、小结三、最后回顾一道面试题总结参考资料 背景 InnoDB一棵B树可以存放多少行数据&#xff1f;这个问题的简单回答是&#xff1a;约2千万。为什么是这么多呢&#xff1f;因为这是可以算出来的&#xff0c;要搞…

[C语言实现]带你手撕带头循环双链表

目录 什么是双链表&#xff1f; 带头结点的优势: 双链表的实现: 什么是循环双链表&#xff1f; 众所周知&#xff0c;顺序表的插入和删除有时候需要大量移动数据&#xff0c;并且每次开辟空间都可能会浪费大量内存和CPU资源&#xff0c;于是我们有了链表&#xff0c;我们之…

【实用篇】SpringCloud01

SpringCloud01 1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.0.学习目标 了解微服务架构的优缺点 1.1.单体架构 单体架构&#xff…

基于复旦微 JFM7K325T 全国产FPGA的高速数据采集、图像处理方案

板卡概述 PCIE-XM711 是一款基于 PCIE 总线架构的高性能数据预处理 FMC载板&#xff0c;板卡采用复旦微的 JFM7K325T FPGA 作为实时处理器&#xff0c;实现 各个接口之间的互联。该板卡可以实现 100%国产化。 板卡具有 1 个 FMC&#xff08;HPC&#xff09;接口&#xff0c;1 路…

这10道测试用例面试题,面试官肯定会问到

前言 软件测试面试中&#xff0c;测试用例是非常容被问到的一个点&#xff0c;今天小编就给大家把最常见的测试用例方面的问题给大家整理出来&#xff0c;希望对大家的面试提供帮助。 1、 什么是测试用例‍ 答&#xff1a;测试用例的设计就是如何覆盖所有软件表现出来的状态…

硬盘有多少图片取决我的网速, Python获取硬盘少女图集

目录 前言开发环境:案例实现的步骤:代码展示尾语 &#x1f49d; 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 图片数据在网络中随处可见, 如果需要一些图片素材 一睹为快把! ! ! 开发环境: 解释器: python 3.8 编辑器: pycharm 2022.3 专业版 内置模块使用 os &g…

CH341的I2C接口编程说明

CH341的I2C接口特性&#xff1a; 1、支持I2C速度20K/100K/400K/750K&#xff1b; 2、默认不支持设备的ACK应答监测&#xff0c;即忽略ACK状态&#xff1b;强制支持需修改软件&#xff1b; 引脚序号功能说明24SCL23SDA Windows系统SPI通讯接口函数 HANDLE WINAPI CH341OpenD…

Piccolo傻瓜式环境配置

首先下载Piccolo的代码 Piccolo下载网址点击Code然后点击Download ZIP。可能有点慢&#xff0c;总共要下139M。 下载CMAKE CMAKE下载网址下载完后安装CMAKE 构建环境 将下来的Piccolo-main压缩包解压为Piccolo-main文件夹。打开CMAKE&#xff0c;如下图进行目录选择&…

Linux - 第19节 - 网络基础(传输层二)

1.TCP相关实验 1.1.理解listen的第二个参数 在编写TCP套接字的服务器代码时&#xff0c;在进行了套接字的创建和绑定之后&#xff0c;需要调用listen函数将创建的套接字设置为监听状态&#xff0c;此后服务器就可以调用accept函数获取建立好的连接了。其中listen函数的第一个参…

LeetCode - 1049 最后一块石头的重量 II (0-1背包)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/130935119 LeetCode:1049. 最后一块石头的重量 II 题目:有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合,从中选…

人脸识别3:C/C++ InsightFace实现人脸识别Face Recognition(含源码)

人脸识别3&#xff1a;C/C InsightFace实现人脸识别Face Recognition(含源码) 目录 1. 前言 2. 项目安装 &#xff08;1&#xff09;项目结构 &#xff08;2&#xff09;配置开发环境(OpenCVOpenCLbase-utilsTNN) &#xff08;3&#xff09;部署TNN模型 &#xff08;4&a…

【C++】手把手教你模拟实现string类

模拟实现string 前言类的成员变量构造函数析构函数size和length[ ] 重载迭代器赋值运算符重载和拷贝构造函数拷贝构造函数赋值运算符重载现代式写法 reserve 和 resizereserveresize 字符串追加push_backappend insertpos位置插字符pos位置插字符串 erase>> 和 <<&…

Linux---用户权限(权限位、chowd、chown)

1. 权限位 序号1&#xff0c;表示文件、文件夹的权限控制信息 序号2&#xff0c;表示文件、文件夹所属用户 序号3&#xff0c;表示文件、文件夹所属用户组 权限细节总共分为10个槽位&#xff1a; 举例&#xff1a;drwxr-xr-x&#xff0c;表示&#xff1a; 这是一个文件夹&…

如何使用Metasploit进行后渗透攻击?

后渗透攻击&#xff08;PostExploitation&#xff09;是整个渗透测试过程中最能够体现渗透测试团队创造力与技术能力的环节。前面的环节可以说都是在按部就班地完成非常普遍的目标&#xff0c;而在这个环节中&#xff0c;需要渗透测试团队根据目标组织的业务经营模式、保护资产…

关于PyQt5的环境搭建

目录 一、需要的环境 二、安装python 1、python安装链接 三、安装PyQt5 1、使用豆瓣的镜像 2、配置环境变量 四、安装pycharm 1、pycharm官网链接 五、配置环境 1、找到设置 2、添加designer 3、配置ui 4、配置rc 六、注意问题 一、需要的环境 1、安装好python安装…

【Linux CAN应用编程(1)】初识CAN总线(附全文代码)

接下来我们学习 CAN 应用编程&#xff0c;CAN 是目前应用非常广泛的现场总线之一&#xff0c;主要应用于汽车电子和工业领域&#xff0c;尤其是汽车领域&#xff0c;汽车上大量的传感器与模块都是通过 CAN 总线连接起来的。CAN 总线目前是自动化领域发展的热点技术之一&#xf…

1、Vue简介与环境搭建

目录 一、Vue简介二、Vue开发环境1 - 环境安装2 - 新建Vue项目3 - VS Code4 - Vue项目的目录结构 一、Vue简介 官方文档&#xff1a;https://cn.vuejs.orgVue的api风格&#xff1a;选项式 API&#xff08;Vue 2&#xff09; 和组合式 API&#xff08;Vue 3&#xff09;**选项式…

怎么把pdf转成word?转换途径一览

在日常生活和工作中&#xff0c;我们常常需要处理各种文档格式。其中&#xff0c;PDF 作为一种流行的跨平台文件格式&#xff0c;广泛应用于技术文档、报告、合同和电子书等领域。但是&#xff0c;当我们需要修改 PDF 文件内容时&#xff0c;却往往会遇到困难。这时&#xff0c…