Springboot扩展点系列之终结篇:Bean的生命周期

2024-03-13 05:10

本文主要是介绍Springboot扩展点系列之终结篇:Bean的生命周期,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

关于Springboot扩展点系列已经输出了13篇文章,分别梳理出了各个扩展点的功能特性、实现方式和工作原理,为什么要花这么多时间来梳理这些内容?根本原因就是这篇文章:Spring bean的生命周期。你了解Spring bean生命周期,这个问题,想回答好其实并不容易,问题太大,涉及到点很多,也复杂,当然在实际业务开发中,这些内容Spring已经帮我们完成了,所以Spring、Springboot用起来才会如此简洁、高效。而这正是我想这件事弄清楚,并分享给更多人的原因:学习优秀的思想,把复杂的事情简单化。

而这篇文章的重点,就是把所有的扩展点串连在一条线上,从宏观和微观分别去了解一下Springboot中bean的生命周期。

Bean的生命周期

Bean的生命周期指的是什么?

简单理解,Spring bean的生命周期,就是普通java类变为Spring管理的Bean的过程,即Spring的核心之一控制反转,即把原来对象创建的控制权由用户程序交由Spring管理。而Spring对普通java类的管理,大致分为两步:第一,先把纳入到Spring管理的java类抽象为一个beanDefinition对象;第二,再根据beanDefinition完成java类的实例化、属性注入、其他的一些Spring特有的扩展操作;第三,这时就可以使用Spring管理的bean,直到bean被销毁。通过这三步普通java类完成了到Spring bean的一个转变,或者说宏观过程来看,这就是Spring bean一个生命周期过程。

普通java类到BeanDefinition

从普通的java类到BeanDefinition,通常有两种方式:

1、在xml中使用等标签进行标记注册;

2、直接在java类上,使用注解形式,如@Component、@Controller、@Service、@Configuration等;

3、第三种比较特殊,利用Spring提供的一些扩展点,直接硬编码的形式实例化好的bean进行注册,如实现FactoryBean接口;

从BeanDefinition到bean的销毁

平时看到的大部分文章的分享,基本是都是分享的这一阶段的内容,这一部分也是步骤最多、逻辑较为复杂的一部分,但是只要把据好两个关键时机,这一部分也可以变得很简单,那这两个时机是什么呢?就是bean的实例化、bean的属性注入。有的小伙伴看源码,看着看着都云里雾里,思路不知道都偏到哪里去了,最后脑子里一片茫然,这是因为没有把握好Bean生命周期的关键。

Bean生命周期的关键是什么呢?答案就是Bean,这可不是废话。不信你试试,所有分析都不要离开bean,牢牢盯好bean在生命周期过程中的变化,你看还会在源码里迷路不?

bean的实例化,也不神秘,即通过java反射调用无参数构造方法或有参数构造方法进行bean实例化,默认是调用无参数构造方法;bean属性注入是指引用Spring容器内对象的属性赋值,即依赖注入;我觉得Spring之所以伟大,除了以上部分,Spring bean生命周期最为值得研究和学习的就在于Bean实例过前后各种丰富、灵活的扩展操作,不仅Spring自己内部在使用,也以接口的形式对外由开发者按自己需要进行实现。因此,我花了一些时间,输出一系列的文章来分享Spring扩展点的功能特性、实现方式、工作原理,如果想从更加微观的角度去了解Spring bean生命周期,可以参考阅读下面这些文章:

1、Springboot扩展点之ApplicationContextInitializer

2、Springboot扩展点之BeanFactoryPostProcessor

3、Springboot扩展点之BeanDefinitionRegistryPostProcessor

4、Springboot扩展点之BeanPostProcessor

5、Springboot扩展点之InstantiationAwareBeanPostProcessor

6、Springboot扩展点之SmartInstantiationAwareBeanPostProcessor

7、Springboot扩展点之ApplicationContextAwareProcessor

8、Springboot扩展点之@PostConstruct

9、Springboot扩展点之InitializingBean

10、Springboot扩展点之SmartInitializingSingleton

11、Springboot扩展点之CommandLineRunner和ApplicationRunner

12、Springboot扩展点之FactoryBean

13、Springboot扩展点之DisposableBean

Spring bean生命周期流程图如下:

Spring bean生命周期涉及主要接口、类的UML关系图如下:

Spring bean生命周期过程,很复杂,但是也有条不紊,主要涉及的的扩展接口有ApplicationContextInitializer、BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor、InstantiationAwareBeanPostProcessor、InitializingBean、BeanPostProcessor、SmartInitializingSingleton、CommandLineRunner、DisposableBean。接口看起来不少,实际上可以分为三类:

1、beanFactory级别:仅在Spring容器启动时执行一次,ApplicationContextInitializer、BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor;

2、bean级别:每个bean实例化、依赖属性注入前后都会触发,InstantiationAwareBeanPostProcessor、BeanPostProcessor;

3、bean自身的方法:bean需要通过属性指定、注解标记或实现接口,如init-method、destroy-method、@PostConstruct注解标记的方法、InitializingBean、DisposableBean、FactoryBean、SmartInitializingSingleton、CommandLineRunner;

概括一下Spring bean生命周期:

1、在Spring容器开始启动到Spring bean(这里主要是指业务中的非懒加载的单例bean)实例化前,是beanFactory级别的扩展接口触发执行,整个生命周期仅执行一次,如ApplicationContextInitializer、BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor;

2、接着通过反射调用bean的构造方法完成bean实例化、bean依赖属性注入;

3、在bean实例化、bean依赖属性注入的前后,bean级别的扩展接口、bean自向的方法触发执行,直到bean销毁,Spring bean的生命周期结束;

面试中经常问Spring Bean生命周期的目的是什么?

其实这个问题对于面试者业说不好回答,因为它实际涉及的内容很多、很广,但是面试官爱问也是有原因的,面试官通过这个问题可以考察到面试者对于Spring从宏观到微观的认识有多深,如果面试者的回答只是几分钟、三言两语,面试官基本上可判定面试者的技术水平比较初级了;如果面试者就这一个问题能聊上一个半小时,依然没有要结束的意思,那么说明面试者对这块理解比较深刻,能力水平自然不必说了。

在面试中,怎么才能回答好这个问题呢?

如果面试官不问你Spring bean的生命周期,是不是学习Spring bean生命周期就没有用了呢?

当然不,Spring生命周期的内容,是Spring的核心、灵魂。不管面试官问什么,你都可以往这上面引。

比如说,面试官问:”平时开发过程中使用Spring boot吗?对Springboot你的理解是什么?“

相信大多数的java项目都会使用Spring、Springboot,可以这样回答:Springboot实际上按约定大于配置的开发原则,对Spring原来XML配置的方式进行简化、包装,可以达到开箱即用,简化开发,提高开发效率,但是其核心依然是Spring。(话锋一转,开始往Spring生命周期上引),而Spring的最重要的核心是IOC,IOC管理的对象就是Spring bean,Spring bean生命周期内的又提供了各种优秀扩展接口和内部实现,也可以根据业务需要自定义实现,非常灵活和方案。然后就可以慢慢聊有哪些扩展接口、功能特性是什么、怎么使用、工作原理是什么,聊上三四个扩展接口,半个小时都不够用。

总结

当然,学习Spring生命周期的内容,并不只是为了面试,其中扩展接口的设计思想、扩展接口在功能特性都可以应用到业务开发中。

这篇关于Springboot扩展点系列之终结篇:Bean的生命周期的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/803730

相关文章

Java五子棋之坐标校正

上篇针对了Java项目中的解构思维,在这篇内容中我们不妨从整体项目中拆解拿出一个非常重要的五子棋逻辑实现:坐标校正,我们如何使漫无目的鼠标点击变得有序化和可控化呢? 目录 一、从鼠标监听到获取坐标 1.MouseListener和MouseAdapter 2.mousePressed方法 二、坐标校正的具体实现方法 1.关于fillOval方法 2.坐标获取 3.坐标转换 4.坐

Spring Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

java8的新特性之一(Java Lambda表达式)

1:Java8的新特性 Lambda 表达式: 允许以更简洁的方式表示匿名函数(或称为闭包)。可以将Lambda表达式作为参数传递给方法或赋值给函数式接口类型的变量。 Stream API: 提供了一种处理集合数据的流式处理方式,支持函数式编程风格。 允许以声明性方式处理数据集合(如List、Set等)。提供了一系列操作,如map、filter、reduce等,以支持复杂的查询和转

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

详细分析Springmvc中的@ModelAttribute基本知识(附Demo)

目录 前言1. 注解用法1.1 方法参数1.2 方法1.3 类 2. 注解场景2.1 表单参数2.2 AJAX请求2.3 文件上传 3. 实战4. 总结 前言 将请求参数绑定到模型对象上,或者在请求处理之前添加模型属性 可以在方法参数、方法或者类上使用 一般适用这几种场景: 表单处理:通过 @ModelAttribute 将表单数据绑定到模型对象上预处理逻辑:在请求处理之前

eclipse运行springboot项目,找不到主类

解决办法尝试了很多种,下载sts压缩包行不通。最后解决办法如图: help--->Eclipse Marketplace--->Popular--->找到Spring Tools 3---->Installed。

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

Java面试题:通过实例说明内连接、左外连接和右外连接的区别

在 SQL 中,连接(JOIN)用于在多个表之间组合行。最常用的连接类型是内连接(INNER JOIN)、左外连接(LEFT OUTER JOIN)和右外连接(RIGHT OUTER JOIN)。它们的主要区别在于它们如何处理表之间的匹配和不匹配行。下面是每种连接的详细说明和示例。 表示例 假设有两个表:Customers 和 Orders。 Customers CustomerIDCus

22.手绘Spring DI运行时序图

1.依赖注入发生的时间 当Spring loC容器完成了 Bean定义资源的定位、载入和解析注册以后,loC容器中已经管理类Bean 定义的相关数据,但是此时loC容器还没有对所管理的Bean进行依赖注入,依赖注入在以下两种情况 发生: 、用户第一次调用getBean()方法时,loC容器触发依赖注入。 、当用户在配置文件中将<bean>元素配置了 lazy-init二false属性,即让