SpringBoot原理解析(二)- Spring Bean的生命周期以及后处理器和回调接口

SpringBoot原理解析(二)- Spring Bean的生命周期以及后处理器和回调接口

文章目录

  • SpringBoot原理解析(二)- Spring Bean的生命周期以及后处理器和回调接口
    • 1.Bean的实例化阶段
      • 1.1.Bean 实例化的基本流程
      • 1.2.Bean 实例化图例
      • 1.3.实例化阶段的后处理器
        • 1.3.1.实例化阶段后处理器的介入流程图
        • 1.3.2.BeanDefinitionRegistryPostProcessor
        • 1.3.3.BeanFactoryPostProcessor
    • 2.Bean的初始化阶段
      • 2.1.主要流程
      • 2.2.初始化流程图
      • 2.3.循环依赖
        • 2.3.1.问题描述
        • 2.3.2.三级缓存
        • 2.3.3.三级缓存流程图
    • 3.Bean的完成阶段
    • 4.Bean的销毁阶段

Spring Bean的生命周期指从Bean的创建(实例化)、初始化,到使用(完成)和销毁的整个过程。

  • Bean的实例化阶段:Spring会取出BeanDefinition的信息进行判断当前Bean的范围是否是singleton的, 是否不是延迟加载的,是否不是FactoryBean等,最终将一个普通的singleton的Bean通过反射进行实例化;

  • Bean的初始化阶段:Bean创建之后还仅仅是个"半成品",还需要对Bean实例的属性进行填充、执行一些Aware 接口方法、执行BeanPostProcessor方法、执行InitializingBean接口的初始化方法、执行自定义初始化init方法 等。该阶段是Spring最具技术含量和复杂度的阶段,Aop增强功能,相关注解功能等、 Bean的循环引用问题都是在这个阶段体现的;

  • Bean的完成阶段:经过初始化阶段,Bean就成为了一个完整的Spring Bean,被存储到单例池 singletonObjects中去了。

  • Bean的销毁阶段:当Bean不再使用时,Spring会调用Bean的销毁方法进行清理工作。

1.Bean的实例化阶段

1.1.Bean 实例化的基本流程

Spring容器在进行初始化时,会将xml配置的的信息封装成一个BeanDefinition对象(详细请见《SpringBoot原理解析(一)- 基于xml配置bean(Java解析xml文件)》),所有的 BeanDefinition存储到一个名为beanDefinitionMap的Map集合中去,Spring框架在对该Map进行遍历,使用反射创建Bean实例对象,创建好的Bean对象存储在一个名为singletonObjects的Map集合中,当调用getBean方法 时则最终从该Map集合中取出Bean实例对象返回。

步骤:

  • 加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefinition对象;

  • 将BeanDefinition存储在一个名为beanDefinitionMap的Map中;

  • ApplicationContext底层遍历beanDefinitionMap,创建Bean实例对象;

  • 创建好的Bean实例对象,被存储到一个名为singletonObjects的Map中;

  • 当执行applicationContext.getBean(beanName)时,从singletonObjects去匹配Bean实例返回

1.2.Bean 实例化图例

在这里插入图片描述

1.3.实例化阶段的后处理器

Spring的后处理器是Spring对外开发的重要扩展点,允许我们介入到Bean的整个实例化流程中来,以达到动态注册 BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用。

  • BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行;

  • BeanDefinitionRegistryPostProcessor:BeanDefinition注册后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行singletonObjects之前执行。

1.3.1.实例化阶段后处理器的介入流程图

在这里插入图片描述

1.3.2.BeanDefinitionRegistryPostProcessor

在Spring容器初始化过程中,首先会加载Bean定义,然后通过注册机制将这些Bean定义注册到容器中。在Bean定义注册的过程中,如果我们需要对Bean定义进行修改或添加一些自定义的处理逻辑,可以实现BeanDefinitionRegistryPostProcessor接口,并实现其中的postProcessBeanDefinitionRegistry 方法。

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {/*** 在所有的Bean定义加载完毕后,但在Bean的实例化和初始化之前执行* 注意:该处理器方法优先于postProcessBeanFactory*/void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;}
1.3.3.BeanFactoryPostProcessor

在Spring容器初始化过程中,当所有的Bean定义加载完成后,但在Bean的实例化和初始化之前,会调用所有实现了BeanFactoryPostProcessor接口的类的postProcessBeanFactory方法。

public interface BeanFactoryPostProcessor {/*** 在所有的Bean定义加载完毕后,但在Bean的实例化和初始化之前执行*/void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}

2.Bean的初始化阶段

2.1.主要流程

Spring Bean的初始化过程涉及如下几个过程,执行优先级从上到下:

  1. org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

  2. Bean的构造器方法

  3. org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

  4. org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessProperties

  5. Bean属性填充

    Bean实例属性填充 Spring在进行属性注入时,会分为如下几种情况:

    • 注入普通属性,String、Integer或存储基本类型的集合时,直接通过set方法的反射设置进去;

    • 注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没有,则先创建被 注入对象Bean实例(完成整个生命周期)后,在进行注入操作;

    • 注入双向对象引用属性时,就比较复杂了,涉及了循环引用(循环依赖)问题。

  6. org.springframework.beans.factory.BeanNameAware#setBeanName

  7. org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader

  8. org.springframework.beans.factory.BeanFactoryAware#setBeanFactory

  9. org.springframework.context.ApplicationContextAware#setApplicationContext

  10. org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization

  11. @postConstruct

  12. org.springframework.beans.factory.InitializingBean#afterPropertiesSet

  13. @Bean注解解析的初始化方法initMethod()

  14. org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization

2.2.初始化流程图

在这里插入图片描述

2.3.循环依赖

2.3.1.问题描述
<!-- userService依赖了orderService -->
<bean id="userService" class="org.ahao.demo.service.UserService"><property name="orderService" re="orderService"/>
</bean><!-- orderService依赖了userService -->
<bean id="orderService" class="org.ahao.demo.service.OrderService"><property name="userService" re="userService"/>
</bean>
2.3.2.三级缓存

通过使用三级缓存,Spring可以提高Bean实例的获取效率和避免循环引用带来的问题。

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {/** Cache of singleton objects: bean name to bean instance. */// ”第一级缓存“:实例化和初始化都完成了的完整Beanprivate final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);/** Cache of early singleton objects: bean name to bean instance. */// ”第二级缓存“:半成品Bean,并且该Bean已经被其他的Bean对象引用了private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);/** Cache of singleton factories: bean name to ObjectFactory. */// “第三级缓存”:半成品Bean,该Bean未被其他的Bean对象引用private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);}

大致流程如下:

  • UserService 实例化对象,但尚未初始化,将UserService存储到第三级缓存singletonFactories;
  • UserService 属性注入,需要OrderService,从缓存中获取,没有OrderService;
  • OrderService实例化对象,但尚未初始化,将OrderService存储到到第三级缓存singletonFactories;
  • OrderService属性注入,需要UserService,从三级缓存获取UserService,UserService从第三级缓存singletonFactories移入第二级缓存earlySingletonObjects;
  • OrderService执行其他生命周期过程,最终成为一个完成Bean,存储到第一级缓存singletonObjects,删除第二三级缓存;
  • UserService 注入OrderService;
  • UserService执行其他生命周期过程,最终成为一个完成Bean,存储到第一级缓存singletonObjects,删除二三级缓存。
2.3.3.三级缓存流程图

在这里插入图片描述

3.Bean的完成阶段

在初始化后,Bean可以被容器和其他Bean使用。此时,Bean处于活动状态,并可以响应外部请求。

@Service
public class OrderServiceImpl implement OrderService {@Autowired// 注入beanprivate UserService userService;@Overridepublic User getOrderUser(long orderId){// 根据订单id获取uidString uid = ...// 使用Bean(已完成初始化,成为一个完整的Bean)return userService.getUserById(uid);}}

4.Bean的销毁阶段

当Bean不再使用时,Spring会调用Bean的销毁方法进行清理工作。可以通过实现DisposableBean接口并实现destroy方法,或使用@PreDestroy注解定义销毁方法。

  • @PreDestroy
  • org.springframework.beans.factory.DisposableBean#destroy

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

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

相关文章

redis的学习(二):常见数据结构及其方法

简介 redis常见的数据结构和他们的常用方法 redis的数据结构 redis是一个key-value的nosql&#xff0c;key一般是字符串&#xff0c;value有很多的类型。 j基本类型&#xff1a; stringhashlistsetsortedSet 特殊类型&#xff1a; GEOBitMapHyperLog key的结构 可以使用…

常用的网络爬虫工具推荐

在推荐常用的网络爬虫工具时&#xff0c;我们可以根据工具的易用性、功能强大性、用户口碑以及是否支持多种操作系统等多个维度进行考量。以下是一些常用的网络爬虫工具推荐&#xff1a; 1. 八爪鱼 简介&#xff1a;八爪鱼是一款免费且功能强大的网站爬虫&#xff0c;能够满足…

mysql练习3

1.修改student 表中年龄(sage)字段属性&#xff0c;数据类型由int 改变为smallint 2.为Course表中Cno 课程号字段设置索引,并查看索引 3.为SC表建立按学号(sno)和课程号(cno)组合的升序的主键索引&#xff0c;索引名为SC_INDEX 4.创建一视图 stu info,查询全体学生的姓名&#…

MinIO使用基础教程

MinIO使用基础教程 一、背景二、快速安装2.1 虚拟机安装2.2 Windows安装2.2.1 下载MinIO服务器2.2.2 启动 MinIO Server2.2.3 通过浏览器访问MinIO服务控制台 三、使用介绍3.1 创建存储桶3.2 上传和下载文件3.3 设置文件公开访问 四、实战SpringBoot Minio实现文件上传和查询五…

思维+01背包,LeetCode LCP 47. 入场安检

一、题目 1、题目描述 「力扣挑战赛」 的入场仪式马上就要开始了&#xff0c;由于安保工作的需要&#xff0c;设置了可容纳人数总和为 M 的 N 个安检室&#xff0c;capacities[i] 记录第 i 个安检室可容纳人数。安检室拥有两种类型&#xff1a; 先进先出&#xff1a;在安检室中…

Git之repo sync -c与repo sync -dc用法区别四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

看准JS逆向案例:webpack逆向解析

&#x1f50d; 逆向思路与步骤 抓包分析与参数定位 首先&#xff0c;我们通过抓包工具对看准网的请求进行分析。 发现请求中包含加密的参数b和kiv。 为了分析这些加密参数&#xff0c;我们需要进一步定位JS加密代码的位置。 扣取JS加密代码 定位到JS代码中的加密实现后&a…

[@Aspect注解爆红]

在SpringAOP的实现过程中&#xff0c;定义切面中通过注解Aspect来声明当前类是一个切面&#xff0c;但是Aspec注解爆红。 上网查询了一下相关原因&#xff0c;才发现在仓库中复制的Spring AOP依赖不正确。 <!--Spring AOP--> <!-- https://mvnrepository.com/artifact…

ARM架构(二)—— arm v7-a/v8/v9寄存器介绍

1、ARM v7-A寄存器 1.1 通用寄存器 V7 V8开始 FIQ个IRQ优先级一样&#xff0c; 通用寄存器&#xff1a;31个 1.2 程序状态寄存器 CPSR是程序状态毒存器&#xff0c;保存条件标志位&#xff0c;中断禁止位&#xff0c;当前处理器模式等控制和状态位。每种异常模式下还存在SPS…

数学建模学习(2)——决策树

import pandas as pd from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import accuracy_score dfpd.read_excel(股票客户流失.xlsx) xdf.drop(columns是否流失)#x等于除是否流失这一列以外的数据…

在Windows安装、部署Tomcat的方法

本文介绍在Windows操作系统中&#xff0c;下载、配置Tomcat的方法。 Tomcat是一个开源的Servlet容器&#xff0c;由Apache软件基金会的Jakarta项目开发和维护&#xff1b;其提供了执行Servlet和Java Server Pages&#xff08;JSP&#xff09;所需的所有功能。其中&#xff0c;S…

Java | Leetcode Java题解之第275题H指数II

题目&#xff1a; 题解&#xff1a; class Solution {public int hIndex(int[] citations) {int n citations.length;int left 0, right n - 1;while (left < right) {int mid left (right - left) / 2;if (citations[mid] > n - mid) {right mid - 1;} else {lef…

uniapp中出现Uncaught runtime errors

项目中运行出现上面的错误信息&#xff0c;使用uniapp发现&#xff0c;其实我只是跨域了&#xff0c;控制台报错&#xff0c;但是不想屏幕上显示&#xff1b; 解决办法是在vue.config.js增加如下配置即可 devServer: {client: {overlay: false,errors:true},}, 错误信息也不想…

【杰理蓝牙开发】AC695x 音频部分

本文主要记录 杰理蓝牙audio接口的使用&#xff0c;包括ADC和DAC原理的介绍和API接口的使用。 【杰理蓝牙开发】AC695x 音频部分 0. 个人简介 && 授权须知1. ADC【音频数据采集】硬件部分1.1 单片机引脚1.2 硬件电路设计1.3 MIC 输入通路解释 2. 【DAC】音频信号编解码…

Apache压测工具ab(Apache Bench)工具的下载安装和使用示例

场景 Jmeter进行http接口压力测试&#xff1a; Jmeter进行http接口压力测试_接口压测两万量-CSDN博客 上面讲压测工具Jmeter的使用&#xff0c;下面介绍另外一个ab(Apache Bench)压测工具的使用。 apache bench apache bench是apache自带的压力测试工具。 ab不仅可以对ap…

MacOS安装SDKMan管理Java版本

文章目录 1 简介2 安装与卸载2.1 安装2.2 卸载 3 使用3.1 查看其他工具&#xff1a;支持 Ant, Maven 等3.2 查看Java版本3.3 安装Java&#xff0c;加上相关的版本3.4 设置Java版本(全局)3.5 只在当前窗口生效3.6 卸载1 默认环境无法卸载 4 jdk安装的位置5 与IDEA集成参考 1 简介…

推荐使用阿贝云免费云服务器、免费虚拟主机

官网地址&#xff1a;https://www.abeiyun.com 阿贝云的免费云服务器简直太棒了&#xff01; 首先&#xff0c;它的性能表现超出了我的预期。在使用过程中&#xff0c;服务器的响应速度非常快&#xff0c;无论是处理日常的网页浏览请求&#xff0c;还是运行一些小型的应用程序…

振荡器和谐振器的区别

首先了解一阶电路知识 一阶电路基础知识-CSDN博客 振荡器&#xff08;Oscillation&#xff09; 振荡器是一种在无外部激励信号下&#xff0c;它能够自激振荡&#xff0c;产生持续交变电压或电流输出&#xff0c;产生连续振荡信号的电路元件。它通过正反馈回路将一部分输出信号…

C++ 设计模式(五)——状态模式

状态模式 序言理解源码 序言 设计模式只是一个抽象的设计模式方法&#xff0c;并不是一个固定使用的搭配&#xff0c;就算是普通switch语句&#xff0c;Map&#xff0c;乃至状态机都是状态模式的其中一种实现方法 状态模式看起来好像和策略模式差不多&#xff0c;主要是其的侧…

企业快速获客-AI机器人批量筛选

那么企业利用AI机器人进行快速获客和批量筛选时&#xff0c;可以遵循以下步骤和策略&#xff0c;以确保高效、准确地获取目标客户&#xff1a; 1. 明确筛客需求 - 企业首先需要明确自身的筛客需求&#xff0c;例如筛选目标客户群、快速识别意向客户等。 - 明确需求有助于…