Bean如何诞生与消亡:生命周期探秘【beans 二】

欢迎来到我的博客,代码的世界里,每一行都是一个故事


在这里插入图片描述

Bean如何诞生与消亡:生命周期探秘【beans 二】

    • 前言
    • bean的创建过程
    • bean的初始化阶段
      • 1. 实现InitializingBean接口:
      • 2. 使用@PostConstruct注解:
    • bean的属性注入
      • 1. Setter注入:
      • 2. 使用@Autowired注解:
    • 自定义初始化方法
    • bean的销毁阶段
      • 1. 实现DisposableBean接口:
      • 2. 使用@PreDestroy注解:
    • 手动销毁bean
    • 生命周期回调顺序
      • 初始化阶段:
      • 销毁阶段:
      • 总体顺序:

前言

在软件开发的世界中,每个对象都有其生命周期,而Spring中的Bean也不例外。Bean的生命周期管理是Spring框架的一项关键功能,它确保了在应用程序运行过程中,每个Bean都能在适当的时候被创建、初始化,并在不再需要的时候被优雅地销毁。本文将以代码为线索,带领你深入探讨Spring Bean的生命周期,让你对Spring框架有更深刻的认识。

bean的创建过程

Bean的创建过程通常是由Spring容器来管理的,其中包括实例化Bean和调用构造函数等步骤。以下是简要的Bean创建过程:

  1. 实例化Bean: Spring容器负责实例化Bean,这是通过使用Java反射机制来完成的。它会查找并加载Bean的类,然后使用newInstance()方法来创建Bean的实例。
// 示例Bean类
public class MyBean {
    public MyBean() {
        // 构造函数
    }
}
  1. 属性注入: 一旦Bean实例被创建,Spring容器会注入所需的属性。这可以通过构造函数注入、Setter方法注入或字段注入来实现。
// 示例Bean类,通过构造函数注入属性
public class MyBean {
    private String name;

    public MyBean(String name) {
        this.name = name;
    }
    
    // Getter和Setter方法可以用于属性的访问和修改
    // ...
}
  1. 初始化回调: 如果Bean实现了InitializingBean接口或在配置文件中定义了初始化方法,Spring容器将调用该方法执行一些初始化操作。
// 示例Bean类,实现InitializingBean接口
import org.springframework.beans.factory.InitializingBean;

public class MyBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        // 在这里执行初始化操作
    }
}
  1. Bean的使用: 完成初始化后,Bean就可以被应用程序的其他部分使用了。
// 示例Bean的使用
MyBean myBean = applicationContext.getBean(MyBean.class);

这就是简单的Bean创建过程。在实际项目中,Bean的创建可能涉及更多的细节,例如Bean的作用域、生命周期等,但上述步骤是基本的创建过程。请注意,以上示例中的代码是为了说明概念,实际项目中可能需要根据具体情况进行适当的调整。

bean的初始化阶段

在Spring中,Bean的初始化阶段可以通过实现InitializingBean接口或使用@PostConstruct注解来完成。以下是这两种方法的示例:

1. 实现InitializingBean接口:

通过实现InitializingBean接口,你可以覆盖afterPropertiesSet方法,在该方法中执行Bean的初始化逻辑。

import org.springframework.beans.factory.InitializingBean;

public class MyBean implements InitializingBean {

    private String name;

    // 其他属性和方法省略

    @Override
    public void afterPropertiesSet() throws Exception {
        // 在这里执行Bean的初始化逻辑
        System.out.println("Bean初始化逻辑执行中...");
    }
}

2. 使用@PostConstruct注解:

通过使用@PostConstruct注解,你可以在方法上添加该注解,标识该方法应该在Bean的初始化阶段被调用。

import javax.annotation.PostConstruct;

public class MyBean {

    private String name;

    // 其他属性和方法省略

    @PostConstruct
    public void init() {
        // 在这里执行Bean的初始化逻辑
        System.out.println("Bean初始化逻辑执行中...");
    }
}

在上述两种方法中,当Spring容器实例化Bean并设置好属性之后,它会检测Bean是否实现了InitializingBean接口或是否有使用了@PostConstruct注解的初始化方法。如果是,容器将在适当的时候调用这些初始化方法。

选择使用哪种方式取决于个人或团队的偏好,通常来说,使用@PostConstruct注解更为灵活,并且不依赖于Spring的特定接口。

bean的属性注入

在Spring中,Bean的属性注入可以通过使用Setter方法和@Autowired注解来实现。以下是这两种方法的示例:

1. Setter注入:

通过Setter方法注入属性,你可以为Bean类提供Setter方法,Spring容器将使用这些方法来设置Bean的属性。

public class MyBean {

    private String name;

    // 其他属性和方法省略

    // Setter方法用于注入name属性
    public void setName(String name) {
        this.name = name;
    }
}

2. 使用@Autowired注解:

通过使用@Autowired注解,你可以在属性上或Setter方法上标记注入点,Spring容器会自动在初始化Bean时注入相关的依赖。

import org.springframework.beans.factory.annotation.Autowired;

public class AnotherBean {

    private MyBean myBean;

    // 其他属性和方法省略

    // 使用@Autowired注解进行属性注入
    @Autowired
    public void setMyBean(MyBean myBean) {
        this.myBean = myBean;
    }
}

在上述两种方法中,Spring容器会检测Bean的属性(通过Setter方法或使用@Autowired注解的属性),并在初始化Bean时注入相应的值或依赖。

选择使用哪种方式通常取决于个人或团队的偏好,以及具体的业务场景。使用Setter注入更为传统,而使用@Autowired注解通常更为简洁。在实际项目中,你可能会选择两者结合使用,根据需要进行灵活配置。

自定义初始化方法

在Spring中,除了使用InitializingBean接口和@PostConstruct注解外,还可以通过自定义初始化方法来完成Bean的初始化。这个方法需要在Spring配置文件或Java配置类中进行定义。以下是一个示例:

public class MyBean {

    private String name;

    // 其他属性和方法省略

    // 自定义初始化方法
    public void customInit() {
        // 在这里执行自定义的初始化逻辑
        System.out.println("执行自定义初始化方法...");
    }
}

在XML配置文件中,你可以使用<bean>元素的init-method属性来指定自定义初始化方法:

<bean id="myBean" class="com.example.MyBean" init-method="customInit">
    <!-- 其他配置属性 -->
</bean>

在Java配置类中,你可以使用@Bean注解的initMethod属性:

@Configuration
public class AppConfig {

    @Bean(initMethod = "customInit")
    public MyBean myBean() {
        return new MyBean();
    }
}

在这个示例中,customInit方法会在Bean被实例化并设置完属性后被调用。你可以在这个方法中执行一些自定义的初始化逻辑。

注意:如果一个Bean同时实现了InitializingBean接口、使用了@PostConstruct注解和自定义初始化方法,它们都会被调用。但建议选择其中一种方式,以保持代码的简洁性和一致性。

bean的销毁阶段

在Spring中,Bean的销毁阶段可以通过实现DisposableBean接口或使用@PreDestroy注解来完成。以下是这两种方法的示例:

1. 实现DisposableBean接口:

通过实现DisposableBean接口,你可以覆盖destroy方法,在该方法中执行Bean的销毁逻辑。

import org.springframework.beans.factory.DisposableBean;

public class MyBean implements DisposableBean {

    private String name;

    // 其他属性和方法省略

    @Override
    public void destroy() throws Exception {
        // 在这里执行Bean的销毁逻辑
        System.out.println("Bean销毁逻辑执行中...");
    }
}

2. 使用@PreDestroy注解:

通过使用@PreDestroy注解,你可以在方法上添加该注解,标识该方法应该在Bean的销毁阶段被调用。

import javax.annotation.PreDestroy;

public class MyBean {

    private String name;

    // 其他属性和方法省略

    @PreDestroy
    public void customDestroy() {
        // 在这里执行Bean的销毁逻辑
        System.out.println("Bean销毁逻辑执行中...");
    }
}

在上述两种方法中,当Spring容器关闭时,它会检测Bean是否实现了DisposableBean接口或是否有使用了@PreDestroy注解的销毁方法。如果是,容器将在适当的时候调用这些销毁方法。

选择使用哪种方式通常取决于个人或团队的偏好,以及具体的业务场景。使用DisposableBean接口是一种标准的Spring方式,而@PreDestroy注解通常更为简洁。在实际项目中,你可能会选择两者结合使用,根据需要进行灵活配置。

手动销毁bean

在Spring中,你可以手动销毁Bean通过调用ApplicationContextclose方法。当你关闭应用程序上下文时,Spring容器将销毁所有已经初始化的Bean。

以下是一个简单的示例:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApp {

    public static void main(String[] args) {
        // 创建应用程序上下文
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // 获取Bean实例
        MyBean myBean = context.getBean(MyBean.class);

        // 使用Bean...

        // 手动销毁Bean,关闭应用程序上下文
        context.close();
    }
}

在上述示例中,当调用context.close()时,Spring容器将销毁所有已经初始化的Bean,包括执行销毁方法(如果Bean实现了DisposableBean接口或使用了@PreDestroy注解)。

这种方式适用于独立应用程序,但在Web应用程序中,通常是通过容器(如Tomcat)来管理应用程序上下文的生命周期。在这种情况下,你不需要手动调用close方法,而是由容器负责销毁Bean。

请注意,在某些情况下,Spring容器可能无法自动感知到应用程序的关闭,因此手动调用close方法是一种确保销毁Bean的可靠方式。

生命周期回调顺序

在Spring中,Bean的生命周期回调方法包括初始化和销毁阶段。以下是不同生命周期回调方法的执行顺序:

初始化阶段:

  1. 构造函数(Constructor): Bean的构造函数首先被调用,创建Bean的实例。

  2. 属性注入(Setter注入、字段注入等): Spring容器注入Bean的属性,包括通过构造函数注入和Setter注入。

  3. 实现InitializingBean接口的afterPropertiesSet方法: 如果Bean实现了InitializingBean接口,Spring容器会在属性注入后调用afterPropertiesSet方法进行初始化。

  4. 使用@PostConstruct注解的方法: 如果Bean中有使用了@PostConstruct注解的方法,这些方法会在上述步骤完成后被调用。

销毁阶段:

  1. 实现DisposableBean接口的destroy方法: 如果Bean实现了DisposableBean接口,Spring容器在关闭时会调用destroy方法进行销毁。

  2. 使用@PreDestroy注解的方法: 如果Bean中有使用了@PreDestroy注解的方法,这些方法会在上述步骤完成后被调用。

总体顺序:

  1. 构造函数
  2. 属性注入
  3. InitializingBean的afterPropertiesSet方法
  4. @PostConstruct注解的方法

(Bean的使用阶段)

  1. @PreDestroy注解的方法
  2. DisposableBean的destroy方法

在这个生命周期过程中,Spring容器负责调用这些回调方法,确保Bean在初始化和销毁阶段都能够执行相应的逻辑。需要注意的是,具体情况可能会受到Bean的作用域、是否懒加载等因素的影响。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

视频倒放软件,看视频如何演绎“逆袭”之旅

你是否厌倦了日复一日的平淡生活&#xff0c;渴望时光倒流&#xff0c;重温那些逝去的精彩瞬间&#xff1f;在数字技术的世界里&#xff0c;这样的愿望或许不再遥不可及。视频倒放仿佛让时光倒流&#xff0c;给我们的视觉带来了全新的冲击&#xff0c;今天&#xff0c;让我们一…

新手第一次在linux上用git上传代码到仓库全过程

目录 背景&#xff1a; 过程&#xff1a; -1.去github.com自己的账号先建个仓库repository 0.命令行输入 git version 看下有无安装git 1.git init 初始化了一个Git仓库&#xff0c;你可以 ls -a 看见这个隐藏的目录 3.git add . 添加要上传的文件到Git的暂存区&#xff0…

windows对微信及小程序抓包:Burp+Fiddler+Proxifier

本文由掌控安全学院 - zbs 投稿 话不多说&#xff0c;直接先上个效果图&#xff1a; 新新的版本哈&#xff1b; 好好的抓包哈&#xff1b; 然后直接说我如何配置的&#xff1a; 准备好三个工具&#xff1a;bp、fiddler、proxifier【也可以用其他的进行代理】 bp、proxifie…

ELement UI时间控件el-date-picker误差8小时解决办法

一、问题描述&#xff1a; 在项目中引用了elementui中的date-picker组件&#xff0c;选中的时间跟实际相差八小时&#xff0c;且格式不是自己想要的格式 <el-date-pickertype"date"placeholder"选择日期"format"yyyy/M/d"v-model"form…

R304S 指纹识别模块的硬件接口说明

一.外部接口尺寸图 二.串行通讯 R304S 指纹模块通讯接口定义&#xff1a; 引脚号名称定义描述15V电源输入电源正输入端 DC 4.2--6V2GND电源和信号地电源和信号地3TXD数据发送串行数据输出&#xff0c;TTL 逻辑电平4RXD数据接收串行数据输入&#xff0c;TTL 逻辑电平 三.USB通…

EtherCAT的COE报文

本文主要用于记录工作中需要学习的内容&#xff0c;如有冒犯请私信&#xff01; COE协议 下面我们介绍以下CANOpen在EtherCAT中的应用。 COE的对象字典 COE协议是完全遵循CANopen协议的&#xff0c;但针对EtherCAT通信做了一些扩展&#xff0c;索引为0x1c00~0x1c4f&#xff0…

Java中关键词strictfp有什么作用?

在Java中&#xff0c;关键词strictfp用于声明一个方法、类或接口是严格遵守浮点数计算规范的。 具体作用包括&#xff1a; 保证浮点数计算的结果在不同平台上是一致的&#xff0c;避免由于浮点数计算的不精确性导致的结果不确定性。 指定了严格的浮点数计算规则&#xff0c;禁…

LeetCode刷题---矩阵置零

解题思路&#xff1a; 本题要求原地置换元素 对矩阵进行第一轮遍历&#xff0c;使用第一行第一列来充当该行该列是否要置换为0的标记位&#xff0c;如果第一行或第一列本身就含有零元素&#xff0c;我们使用colZero和rowZero变量来对其标记。如果第i行第j列的那个元素为0&#…

产品经理如何选择城市?

年底&#xff0c;全国性的人口大迁徙即将开始。选择城市&#xff0c;堪称年轻人的“二次投胎”&#xff0c;族望留原籍&#xff0c;家贫走他乡。 古人在选择城市时&#xff0c;主要的考量因素是家族势力&#xff0c;这一点放在当代&#xff0c;大致也成立&#xff0c;如果在老…

Cell 文章图复现

多组差异火山图复现 参考文章: A Spatiotemporal Organ-Wide Gene Expression and Cell Atlas of the Developing Human Heart Figure 2. H 图里主要是单细胞数据不同cluster之间的差异火山图, 所以说白了就是散点图和柱状图的结合, 散点图用差异基因绘制, 柱状图利用logFC最…

关于MIPS上手应知应会-如何把C语言改写为MIPS!

文章目录 寄存器指令使用技巧翻译C/Cif/else语句switch语句for循环while 循环do...while循环一维数组定义与使用二维数组定义与使用例 &#xff1a;哈密顿回路 注意立即数被符号位扩展 参考链接 寄存器 NameReg. NumUsage z e r o zero zero0constant value 0(恒为0) a t at a…

TypeScript Array(数组)

目录 1、数组初始化 2、Array 对象 3、数组迭代 4、数组在函数中的使用 4.1、作为参数传递给函数 4.2、作为函数的返回值 5、数组方法 数组对象是使用单独的变量名来存储一系列的值。数组非常常用。假如你有一组数据&#xff08;例如&#xff1a;网站名字&#xff09;…

Java中的IO与NIO篇----第三篇

系列文章目录 文章目录 系列文章目录前言一、信号驱动 IO 模型二、异步 IO 模型三、JAVA NIO四、NIO 的缓冲区前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、…

P1423 小玉在游泳python

s float(input()) sum 0 step 0 meter 2.0 while sum < s:sum metermeter 0.98 * meterstep 1 print(step)

三、C语言中的分支与循环—switch语句(4)分支结构 完

本章分支结构的学习内容如下&#xff1a; 三、C语言中的分支与循环—if语句 (1) 三、C语言中的分支与循环—关系操作符 (2) 三、C语言中的分支与循环—条件操作符 与逻辑操作符(3) 三、C语言中的分支与循环—switch语句&#xff08;4&#xff09;分支结构 完 本章循环结构的…

linux创建pyspark虚拟环境

一、创建虚拟环境 conda create -n test python3.6.6 二、注意添加镜像 vi /root/.condarc channels:- http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/- http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/- http://mirrors.ustc.edu.cn/anaconda/pkgs/ma…

jmeter使用心得(一)

jmeter作为接口测试的常用工具之一&#xff0c;在我们的测试中经常会用到&#xff0c;往期的文章中&#xff0c;我们也分享过jmeter的各种功能和用法&#xff0c;基本覆盖了方方面面&#xff0c;可以满足各种接口测试的需求。但实际测试中我们也会发现&#xff0c;jmeter这么强…

测试管理-缺陷管理工具安装

前言&#xff1a; 项目生命周期里面&#xff0c;开发软件后&#xff0c;需要进行正规的测试&#xff0c;测试除了需要编写测试用例和写测试总结外&#xff0c;还需要进行bug的闭环控制&#xff0c;方便追踪。之前用过惠普的QC系统&#xff0c;这个是收费的&#xff0c;专业做缺…

【网络】网络层IP地址和IP数据报的格式

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&am…

图像分割 分水岭法 watershed

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 本文的C#版本请访问&#xff1a;图像分割 分水岭法 watershed&#xff08;C#&#xff09;-CSDN博客 Watershed算法是一种图像处理算…