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

spring框架学习(下)

这章节讲的主要是spring在生产Bean对象时的过程

Spring实例化对象的基本流程

1、解析bean.xml

2、封装成BeanDifinition

3、存放到BeanDIfinitionMap

4、从BeanDIfinitionMap遍历得到bean

5、将bean存放到SingletonObjects

6、调用getBean方法得到bean

以下是简易的流程图:

郭尘帅
郭尘帅666

1、Bean的处理器(xxxxPostProcessor)

基础概念:Spring的后处理是Spring对外开发的重要扩展点,它允许我们介入到Bean的整个实例化流程中来,可以动态添加、修改BeanDefinition、动态修改Bean。

Spring主要有两种后处理器:一种是Bean工厂后处理器BeanFactoryPostProcessor)另一种是Bean后处理器BeanPostProcessor)。

区别在于:

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

Bean后处理器一般在bean实例化后,填充到单例池SingletonObjectes之前执行;

但是我还没有研究透彻,还不能很好的说明,所以就先跳过这个知识点

2、Bean的生命周期

Spring Bean 的生命周期可以概括为以下几个主要阶段:

  1. 实例化:容器借助反射机制创建 Bean 的实例。
  2. 属性赋值:为 Bean 的属性注入值,这些值可能来自配置文件、注解等。
  3. 初始化:执行初始化方法,例如实现 InitializingBean 接口的 afterPropertiesSet 方法,或者使用 @PostConstruct 注解的方法。
  4. 使用:Bean 被应用程序使用。
  5. 销毁:执行销毁方法,例如实现 DisposableBean 接口的 destroy 方法,或者使用 @PreDestroy 注解的方法。
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;// 定义一个 Bean 类
public class MyBean implements InitializingBean, DisposableBean {private String message;// 构造函数,用于实例化 Beanpublic MyBean() {System.out.println("MyBean: 实例化");}// 属性赋值方法public void setMessage(String message) {this.message = message;System.out.println("MyBean: 属性赋值 - message = " + message);}// 使用 @PostConstruct 注解的初始化方法@PostConstructpublic void postConstruct() {System.out.println("MyBean: @PostConstruct 注解的初始化方法");}// 实现 InitializingBean 接口的 afterPropertiesSet 方法@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("MyBean: InitializingBean 接口的 afterPropertiesSet 方法");}// 自定义的初始化方法public void initMethod() {System.out.println("MyBean: 自定义的初始化方法");}// 使用 @PreDestroy 注解的销毁方法@PreDestroypublic void preDestroy() {System.out.println("MyBean: @PreDestroy 注解的销毁方法");}// 实现 DisposableBean 接口的 destroy 方法@Overridepublic void destroy() throws Exception {System.out.println("MyBean: DisposableBean 接口的 destroy 方法");}// 自定义的销毁方法public void destroyMethod() {System.out.println("MyBean: 自定义的销毁方法");}// 获取消息的方法public String getMessage() {return message;}
}

配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")public MyBean myBean() {MyBean bean = new MyBean();bean.setMessage("Hello, Spring!");return bean;}
}

 测试类

import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Main {public static void main(String[] args) {// 创建 Spring 容器AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 获取 BeanMyBean myBean = context.getBean(MyBean.class);System.out.println("MyBean: 使用 - message = " + myBean.getMessage());// 关闭容器,触发 Bean 的销毁过程context.close();}
}

 代码解释

2.1 MyBean 类

  • 构造函数:在 Bean 实例化时调用。
  • setMessage 方法:用于为 Bean 的属性赋值。
  • @PostConstruct 注解的方法:在属性赋值后、初始化方法之前调用。
  • afterPropertiesSet 方法:实现 InitializingBean 接口的方法,在 @PostConstruct 方法之后调用。
  • initMethod 方法:自定义的初始化方法,在 afterPropertiesSet 方法之后调用。
  • @PreDestroy 注解的方法:在容器关闭前、销毁方法之前调用。
  • destroy 方法:实现 DisposableBean 接口的方法,在 @PreDestroy 方法之后调用。
  • destroyMethod 方法:自定义的销毁方法,在 destroy 方法之后调用。

2.2 AppConfig 类

  • @Bean 注解:用于定义一个 Bean,initMethod 和 destroyMethod 属性分别指定了自定义的初始化方法和销毁方法。

2.3 Main 类

  • 创建 AnnotationConfigApplicationContext 容器,并加载 AppConfig 配置类。
  • 获取 MyBean 实例并使用。
  • 关闭容器,触发 Bean 的销毁过程。

输出结果为:

MyBean: 实例化
MyBean: 属性赋值 - message = Hello, Spring!
MyBean: @PostConstruct 注解的初始化方法
MyBean: InitializingBean 接口的 afterPropertiesSet 方法
MyBean: 自定义的初始化方法
MyBean: 使用 - message = Hello, Spring!
MyBean: @PreDestroy 注解的销毁方法
MyBean: DisposableBean 接口的 destroy 方法
MyBean: 自定义的销毁方法

 总结:

Spring Bean 的生命周期是一个复杂而有序的过程,通过实现不同的接口和使用注解,我们可以在 Bean 的不同阶段插入自定义的逻辑。理解 Bean 的生命周期有助于我们更好地控制 Bean 的创建、初始化和销毁过程,提高应用程序的性能和可维护性。

相关文章:

spring框架学习(下)

这章节讲的主要是spring在生产Bean对象时的过程 Spring实例化对象的基本流程 1、解析bean.xml 2、封装成BeanDifinition类 3、存放到BeanDIfinitionMap里 4、从BeanDIfinitionMap遍历得到bean 5、将bean存放到SingletonObjects 6、调用getBean方法得到bean 以下是简易的…...

进程与线程-----C语言经典题目(8)

一.什么是进程 定义: 进程指的是程序在操作系统内的一次执行过程。它不只是程序代码,还涵盖了程序运行时的各类资源与状态信息。包括创建、调度、消亡。 进程的状态(ps -aux): 就绪状态:进程已经…...

lstm用电量预测+网页可视化大屏

视频教学: 训练结果: 详细代码: import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler from sklearn.model_selection import train_test_split from tensorflow.keras.models import Sequential from tensorflow.keras.layers impo…...

linux blueZ 第六篇:嵌入式与工业级应用案例——在 Raspberry Pi、Yocto 与 Buildroot 上裁剪 BlueZ 并落地实战

本篇面向嵌入式与工业级应用场景,深入讲解如何在各类 Linux 构建系统(Raspberry Pi OS、Yocto、Buildroot)中裁剪、交叉编译与集成 BlueZ,以及在工业网关、资产追踪与蓝牙 Mesh 等典型方案中的落地实例与注意要点,帮助你打造稳定、可维护、低功耗的嵌入式蓝牙产品。 目录 …...

Dev控件RadioGroup 如何设置一排有N个显示或分为几行

1.5个选项 全部横排显示,则Columns 5 2.5个选项 每行分两个,则有三行,则Columns 2...

AOSP Android14 Launcher3——Launcher的状态介绍LauncherState类

Launcher3中有一个跟Launcher状态相关的类,叫LauncherState LauncherState 是 Launcher3 中定义各种用户界面状态的抽象基类。你可以把它想象成一个状态机,定义了 Launcher 可能处于的不同视觉和交互模式,例如主屏幕、所有应用列表、最近任务…...

Redis 笔记(三)-Redis 基本知识及五大数据类型

一、redis 基本知识 redis 默认有 16个 数据库,config get databases 查看数据库数量 127.0.0.1:6379> config get databases # 查看数据库数量 1) "databases" 2) "16"默认使用的是第 0个 16 个数据库为:DB 0 ~ DB 15&am…...

Linux——线程(2)线程互斥(锁)

知识回顾 在学习本篇内容前,我们需要先回顾一下几个概念。 临界资源:多线程执行流共享的资源就叫做临界资源 临界区:每个线程内部,访问临界资源的代码,就叫做临界区 互斥:任何时刻,互斥保证有…...

深度解析:具身AI机器人领域最全资源指南(含人形机器人,多足机器人,灵巧手等精选资源)

💡 你是否在寻找具身人工智能(Embodied AI)领域的研究资源?是否希望有一个系统性的资源集合来加速你的研究?今天给大家推荐一个重磅项目! 🌟 为什么需要这个项目? 具身人工智能是一…...

组件之间的信息传递的四种方法!!【vue3 前端】

迎万难 赢万难! 目录 1. 使用 defineProps 传递数据:2. 使用。defineEmits 发送事件:3. 使用 Provide / Inject:4. 使用状态管理(如 Pinia): 1. 使用 defineProps 传递数据: 父组件…...

单片机学习笔记9.数码管

0到99计数 ,段选共阴极 ;0到99计数 ORG 0000H LJMP MAIN ORG 000BH LJMP TIMER0_ISR ORG 0100H; 定义位选控制位 DISPLAY_SELECT BIT 20H.0MAIN:; 定时器 0 初始化MOV TMOD, #01H ; 设置定时器 0 为模式 1MOV TH0, #3CH ; 定时器 0 高 8 位初值,定时 …...

Go 语言 核心知识点

Go 语言(Golang)是由 Google 开发的一种静态类型、编译型语言,设计目标是高效、简洁、并发友好。它借鉴了 C 语言的性能优势,同时引入了现代语言的特性(如垃圾回收、并发原语),并摒弃了传统面向…...

【C++ 类和数据抽象】消息处理示例(2)

目录 一、消息处理系统的核心价值 1.1 现代软件架构中的消息驱动 1.2 消息处理系统的关键组件 二、消息处理系统概述 三、Message类设计 3.1 成员变量 3.2. 成员函数 3.3. 私有辅助函数 四、Folder类设计 五、代码实现 六、数据抽象在消息处理系统中的应用 七、总结…...

kafka 中消费者 groupId 是什么

📚 什么是 groupId? groupId 是 Kafka 里消费者组(Consumer Group)的唯一标识。 同一个 groupId 的消费者,一起共享消费,一条消息只给组内一个消费者处理。不同 groupId 的消费者组,各自独立消…...

单相交直交变频电路设计——matlab仿真+4500字word报告

微♥“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 硬件电路采用Altium designer设计,仿真采用Matlab软件 本仿真模型基于MATLAB/Simulink(版本MATLAB 2018Rb)软件。建议采用matlab2018Rb及以上版本打开。(若需要其他…...

Python中的协程(Coroutine)

Python中的协程(Coroutine) 是一种轻量级的异步执行单元,主要用于解决IO密集型任务的性能问题。Python 3.5引入了 async/await 语法,使得协程变得简洁且易于使用。协程的核心是通过事件循环(Event Loop) 来…...

【QT】QT多线程

QT多线程 1.涉及到类和方法示例代码:未重写run函数 2.使用思路3.常用方法4.示例代码1:重写线程run函数现象: 5.示例代码2:多线程显示切换图片,使用公有方法现象: 1.涉及到类和方法 类:QThread 示…...

基于深度学习的医疗诊断辅助系统设计

标题:基于深度学习的医疗诊断辅助系统设计 内容:1.摘要 随着医疗数据的爆炸式增长和深度学习技术的飞速发展,开发基于深度学习的医疗诊断辅助系统具有重要的现实意义。本研究的目的在于设计一个高效、准确的医疗诊断辅助系统,以辅助医生进行更精准的诊断…...

C++ RAII

RAII(Resource Acquisition Is Initialization,资源获取即初始化)是 C 编程中的核心设计理念,用于管理资源的分配和释放。它通过将资源的生命周期绑定到对象的生命周期,利用 C 的自动对象管理机制(主要是栈…...

Linux进程学习【环境变量】进程优先级

进程优先级的基本概念 在 Linux 中,每个进程都有一个优先级,操作系统根据这个优先级来决定进程的执行顺序。优先级越高,进程的执行就越频繁。通常,进程优先级是由以下两个部分构成: 静态优先级(PRI&#x…...

Leetcode:283. 移动零

题目 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nums [0]…...

BIOES 标签的含义

BIOES 标签的含义 ​B (Begin) 表示一个实体的开始。例如,在句子 “北京是中国的首都” 中,“北京” 作为地点实体的开头,首字会被标注为 B-LOC,后续字可能标注为 I-LOC。 ​I (Inside) 表示一个实体的中间或内部部分。例如&a…...

mAh 与 Wh:电量单位的深度解析

1. 基础定义与物理意义 1.1 mAh(毫安时) 定义:表示电池以毫安(mA)为单位的电流持续放电 1 小时的电荷量。1 mAh1 mA1 h3.6 C(库仑,电荷单位)局限性:仅反映电池存储的电荷量,未考虑电…...

安卓屏播放语音失败,报错TextToSpeech: speak failed: not bound to TTS engine

最近碰到一个很棘手的问题,无缘无故,之前在Android9.0跑得好好的程序,升级安装系统到Android13后,就发现之前能放的语音,现在放不了了,真是头大,所以我摸索着尝试解决,且看我的解决过…...

C语言学习之结构体

在C语言中,我们已经学了好几种类型的数据。比如整型int、char、short等,浮点型double、float等。但是这些都是基本数据类型,而这些数据类型应用在实际编程里显然是不够用的。比如我们没有办法用一旦数据类型来定义一个”人“的属性。因此这里…...

layui获取无法获取表单数据,data.field一直为空

form.on(submit(*), function(data){console.log(data.field) //当前容器的全部表单字段,名值对形式:{name: value}return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。}); console.log(data.field)一直显示为空&#xff0…...

「Mac畅玩AIGC与多模态02」部署篇01 - 在 Mac 上部署 Ollama + Open WebUI

一、概述 本篇介绍如何在 macOS 环境下本地部署 Ollama 推理服务,并通过 Open WebUI 实现可视化交互界面。该流程无需 CUDA 或专用驱动,适用于 M 系列或 Intel 芯片的 Mac,便于快速测试本地大语言模型能力。 二、部署流程 1. 环境准备 安装 Homebrew(如尚未安装):/bin…...

量子力学:量子通信

量子通信是利用量子力学原理对信息进行编码、传输和处理的新型通信方式,以下是其详细介绍及业界发展现状: 基本原理 量子叠加态 :量子系统可以处于多个状态的叠加,如光子的偏振方向可以同时处于水平和垂直方向的叠加态&#xff…...

《大型网站技术架构-核心原理与案例分析》笔记

:::info 💡 根据 遗忘曲线:如果没有记录和回顾,6天后便会忘记75%的内容 读书笔记正是帮助你记录和回顾的工具,不必拘泥于形式,其核心是:记录、翻看、思考::: 书名大型网站技术架构-核心原理与案例分析作者…...

log4cpp进阶指南

📝 log4cpp进阶指南 1. 按天切割日志 log4cpp 默认是按文件大小来切割日志的。为了按天切割日志,通常需要自己进行时间判断并手动处理日志文件的切割。 1.1 解决方案 虽然 RollingFileAppender 只支持按大小切割,但你可以使用以下策略&…...

树莓派超全系列教程文档--(43)树莓派内核简介及更新

树莓派内核简介及更新 简介更新 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 简介 Raspberry Pi 内核是 托管在 GitHub 上;更新滞后于上游 Linux内核。上游内核持续更新,而 Raspberry Pi 则将 Linux 内核的长期版本整合…...

第二章、在Windows上部署Dify:从修仙小说到赛博飞升的硬核指南

第1章:安装 wsl (Windows Subsystem for Linux) 上一章我们聊了什么是Dify,这一章我们讲一下怎么才能用Dify。 使用Dify就需要我们在本地部署Dify; 部署Dify就需要用到”Docker“; 要想使用“Docter”就需要用到wsl。 那什么是wsl呢?简单来说就是让你的电脑拥有另一个叫…...

淘宝商品主图标题api接口

1、输入淘宝商品id或者链接,点查询 2、查询淘宝商品主图,商品标题,商品价格,卖家旺旺 3、支持api接口...

小结:BFD

*BFD(双向转发检测,Bidirectional Forwarding Detection)是一种快速、轻量级的故障检测机制,用于检测网络中两点之间的连通性。它广泛应用于各种场景 1. 检测 IP 链路 应用场景: BFD 用于检测两台设备之间的 IP 层连…...

收藏按钮变色问题

1.问题描述 无论是否收藏,收藏按钮都显示黄色,但点击收藏按钮后却能发生颜色变化 2.解决思路 经过调试发现isCollected返回的是整个对象,因此在store的方法里面找到了相应的函数进行修改使得isCollected返回相应的值 修改前: 修…...

小程序发布后,不能强更的情况下,怎么通知到用户需要去更新?

哈喽,我想和大家分享一下我在开发记账小程序时遇到的一个问题,以及我找到的解决办法。 这个记账小程序从一开始,我就特别在意用户的隐私,所以把记账数据都存到了本地缓存里,还做了个手动备份的功能。但系统嘛&#xf…...

4.2.2 MySQL索引原理以及SQL优化

文章目录 4.2.2 MySQL索引原理以及SQL优化1. 索引与约束1. 索引是什么2. 索引的目的3. 几种索引4. 约束1.外键2. 约束 vs 索引的区别 5. 索引实现1. 索引存储2. 页3. B树4. B树层高问题5. 自增id6. 聚集索引7. 辅助索引 8. innnodb体系结构1. buffer pool2. change buffer 9. 最…...

02_值相同、类型不同,用 equals() 比较为什么是 false?

02_值相同、类型不同&#xff0c;用 equals() 比较为什么是 false&#xff1f; 场景示例 Map<Long, String> map; Integer keyWord 4; if (map.containsKey(keyWord)) {// ... }结果&#xff1a; → 编译通过&#xff0c;但 containsKey 返回 false&#xff0c;逻辑错…...

leetcode--盛最多水的容器,接雨水

11.盛最多水的容器 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不…...

AlexNet网络搭建

AlexNet网络模型搭建 环境准备 首先在某个盘符下创建一个文件夹&#xff0c;就叫AlexNet吧&#xff0c;用来存放源代码。 然后新建一个python文件&#xff0c;就叫plot.py吧&#xff0c;往里面写入以下代码&#xff0c;用于下载数据集&#xff1a; # FashionMNIST里面包含了…...

常用第三方库:sqflite数据库应用

常用第三方库&#xff1a;sqflite数据库应用 一、基础概念 1.1 什么是sqflite&#xff1f; sqflite是Flutter官方推荐的SQLite数据库插件&#xff0c;它提供了在Flutter应用中使用SQLite数据库的能力。SQLite是一个轻量级的、嵌入式的关系型数据库&#xff0c;特别适合移动应…...

【论文阅读】-周总结-第5周

1. 【论文阅读24】并行 TCN-LSTM 风电预测模型&#xff08;2024-02&#xff09; 链接 论文信息&#xff1a; Liu S, Xu T, Du X, et al. A hybrid deep learning model based on parallel architecture TCN-LSTM with Savitzky-Golay filter for wind power prediction. Ener…...

深入理解 JavaScript 的 typeof 运算符:返回的数据类型

JavaScript 的 typeof 运算符是开发中用于检测值类型的基础工具。虽然看似简单&#xff0c;但其行为存在需要开发者理解的微妙细节。本文将解析 typeof 返回的数据类型&#xff0c;探讨边界案例&#xff0c;并分享类型检查的最佳实践。 typeof 会返回哪些类型&#xff1f; typ…...

前端零基础入门到上班:【Day8】JavaScript 基础语法入门

前端零基础入门到上班:【Day8】JavaScript 基础语法入门&#xff08;超全&#xff01;&#xff01;&#xff01;&#xff09; 一、JavaScript 简介二、引入 JavaScript 的三种方式三、变量与常量&#xff08;var、let、const&#xff09;3.1 var &#xff08;传统方式&#xff…...

ppt流程图怎么?ppt流程图模板大全

ppt流程图怎么&#xff1f;ppt流程图剪头模板&#xff0c;ppt流程图模板大全: ppt流程图_模板素材_PPT模板_ppt素材_免抠图片_AiPPTer...

makefile总结

Makefile 学习视频&#xff1a;1、野火的基础入门篇-第32讲 Makefile三要素_哔哩哔哩_bilibili ​ 2、b站视频04 一个稍复杂的Makefile_哔哩哔哩_bilibili 学习资料&#xff1a;第2个视频对应的Make/make.md 无限十三年/CPP - 码云 - 开源中国 ch0_Makefile简介 Makefile是什…...

MIME 类型是个什么东西?

MIME 类型&#xff08;Multipurpose Internet Mail Extensions&#xff09;即多用途互联网邮件扩展类型&#xff0c;它是一种标准&#xff0c;用于表示文档、文件或字节流的性质和格式。 最初设计用于电子邮件系统&#xff0c;后来被广泛应用于网页、HTTP 协议等领域&#xff0…...

javaWeb开发---前后端开发全景图解(基础梳理 + 技术体系)

在现代互联网开发中&#xff0c;前端与后端的分工协作非常重要。本文结合实际架构图&#xff0c;全面梳理前端技术栈、后端技术栈以及服务器端整体流程&#xff0c;帮助初学者建立清晰的整体认知。 一、整体架构概览 系统整体划分为三个主要部分&#xff1a; B端&#xff08;…...

spring-rabbit的CachingConnectionFactory默认参数导致消费者Channel数量暴增问题解决

文章目录 1.前言2.解决2.1消费监听方法中关闭channel2.2 配置设置两个参数 3.总结 1.前言 由于之前写了一个好用的rabbitmq-spring-boot-start启动器&#xff0c;后面在生产实践之后反馈消费者连接的Channel数量过多&#xff0c;一个消费者的Channel数量可以达到好几百&#xf…...

线上JVM调优与全栈性能优化 - Java架构师面试实战

线上JVM调优与全栈性能优化 - Java架构师面试实战 本文通过一场互联网大厂的Java架构师面试&#xff0c;深入探讨了线上JVM调优、OOM定位、死锁定位、内存和CPU调优、线程池调优、数据库调优、缓存调优、网络调优、微服务调优及分布式调优等关键领域。 第一轮提问 面试官&am…...