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

news2025/6/10 12:50:52

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


在这里插入图片描述

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.coloradmin.cn/o/1354963.html

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

相关文章

基于ssm的《数据库系统原理》课程平台的设计与实现论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

RA4803SA (高稳定实时时钟模块)

汽车用RA4803SA&#xff0c;高稳定串行接口实时时钟模块内置频率可调32.768kHz晶体单元和DTCXO。1/100秒分辨率时间寄存器接口类型4线串行接口界面电压范围1.6V ~ 5.5V温度补偿电压范围2.2V至5.5V时钟电源电压范围1.6V ~ 5.5V可选时钟输出(32.768kHz, 1024Hz, 1Hz)各种功能包括…

深入浅出Prometheus架构原理

目录 1 Prometheus简介 2 Prometheus 的优势 2.1 Prometheus 适用于什么场景 2.2 Prometheus 不适合什么场景 3 Prometheus 的架构 4 Prometheus 的组件 4.1 组件介绍 4.1.1 Prometheus Server 4.1.2 Exporter 4.1.3 Push Gateway 4.1.4 Grafana 4.1.5 Alert…

2024年防止内卷和被潜规则,RocketMQ消息中间件实战派上下册上线啦|架构随笔录

2023已经过去啦&#xff0c;作为技术小伙伴一定要做好2024年的规划&#xff0c;只有这样才能够避免内卷和潜规则。 2024年即将是一个重新开始的一年&#xff0c;但是你要说互联网不倦&#xff0c;那是不可能的&#xff0c;就连某大厂都开始走下坡路啦&#xff0c;里面卷的是不…

NGUI基础-图集制作(保姆级教程)

目录 图集是什么 如何打开图集制作工具 制作步骤 图集的三个关键配置 相关参数介绍 Atlas Material Texture Padding Tim Alpha PMA shader Unity Packer TrueColor Auto-upgrade Force Square Pre-processor 图集是什么 Unity图集&#xff08;Sprite Atlas&…

力扣hot100 二叉树展开为链表 递归 特殊遍历

&#x1f468;‍&#x1f3eb; 题目地址 &#x1f469;‍&#x1f3eb; 参考题解 &#x1f60b; 将左子树插入到右子树上 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* …

【设计模式之美】面向对象分析方法论与实现(二):需求到接口实现的方法论

文章目录 一. 进行面向对象设计1. 划分职责>需要有哪些类2. 定义类及其属性和方法3. 定义类与类之间的交互关系4. 将类组装起来并提供执行入口 二. 如何进行面向对象编程&#xff1f;1. 接口实现2. 辩证思考与灵活应用 【设计模式之美】面向对象分析方法论与实现&#xff08…

二叉树链式结构的实现(二叉树的遍历以及各种常用功能函数的实现)

之前也是把堆部分的知识点梳理完毕&#xff08;即二叉树链式顺序的实现&#xff09;&#xff1a;堆的应用&#xff1a;堆排序和TOP-K问题 那么讲完了二叉树链式结构的实现。今天就进入二叉树链式结构的实现&#xff1a; 文章目录 1.准备工作2.二叉树的遍历2.1前序遍历2.2中序遍…

从vue小白到高手,从一个内容管理网站开始实战开发第三天,使用Element UI构建页面-登录(一)

上次我们介绍了如何安装Element UI库,这次我们使用Element UI中的组件开始开发我们的页面。 开发之前要先在项目中建立好几个目录,方便我们下面的开发。 一、在项目中创建页面管理目录 1、pages目录(文件夹) 首先在src文件夹下创建一个名为pages的文件夹,该文件夹用来统…

elasticsearch的查询方式和数据库事务隔离级别的思考

项目中用到了 elasticsearch&#xff0c;发现有几种查询方式不太一样&#xff0c;思考了一下&#xff0c;总结如下 普通分页 等同于关系数据库的分页查询&#xff0c;例如 mysql 的 limit&#xff0c;如下 sql select * from test limit 100000,10 这种查询方式有一个问题&a…

软文推广宣发遵循的基本流程

在软文发稿的旅程中&#xff0c;制定明确的策略思路是确保成功的关键。软文发稿有一定的流程需要我们遵循&#xff0c;才能达到理想的软文宣发效果。首先&#xff0c;我们要明确发稿的地区&#xff0c;然后精准选择目标受众&#xff0c;最后才能展开内容的创作。下面&#xff0…

springboot整合springbatch批处理

springboot整合springbatch实现批处理 简介项目搭建步骤 简介 项目搭建 参考博客【场景实战】Spring Boot Spring Batch 实现批处理任务&#xff0c;保姆级教程 步骤 1.建表 建表sql CREATE TABLE student (id int NOT NULL AUTO_INCREMENT,name varchar(100) NOT NULL C…

02-SpringCloud-Eureka注册中心

Eureka注册中心 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图&#xff1a; 大家思考几个问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址和端口&#xff1f;有多个user-service实例地址&#xff0c;…

力扣hot100 翻转二叉树 递归

&#x1f468;‍&#x1f3eb; 题目地址 &#x1f60b; AC code /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNod…

CNN——AlexNet

1.AlexNet概述 论文原文&#xff1a;ImageNet Classification with Deep Convolutional Neural Networks 在LeNet提出后&#xff0c;卷积神经网络在计算机视觉和机器学习领域中很有名气。但卷积神经网络并没有主导这些领域。这是因为虽然LeNet在小数据集上取得了很好的效果&am…

jQuery常用的 四大基本选择器

文章目录 简介&#xff1a;基础选择器1. 通过 ID 选择器获取元素2. 通过 class 选择器获取元素3. 通过标签名选择器获取元素 层级选择器1. 通过直接子元素选取2. 通过后代元素选取 属性选择器1.[attributevalue]属性选择器2.[attribute!value] 属性选择器3.[attribute*value]属…

如何在Windows安装Wnmp服务并实现固定地址远程访问

文章目录 前言1.Wnmp下载安装2.Wnmp设置3.安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4.固定公网地址访问 前言 WNMP是Windows系统下的绿色NginxMysqlPHP环境集成套件包&#xff0c;安装完成后即可得到一个Nginx MyS…

字符串处理-第11届蓝桥杯省赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第26讲。 字符串处理&#…

Typescript---webpack和Babel的使用 03

webpack 通常情况下&#xff0c;实际开发中我们都需要使用构建工具对代码进行打包&#xff0c;TS同样也可以结合构建工具一起使用&#xff0c;下边以webpack为例介绍一下如何结合构建工具使用TS。 步骤&#xff1a; 初始化项目 进入项目根目录&#xff0c;执行命令 npm init -…

Dockerfile + harbor详解

Dockerfileharbor私服 一 docker工作流 1. docker管理流程 2. 镜像仓库阿里 (1) 阿里私有仓库 公司内部管理项目涉及到的所有docker镜像&#xff0c;会使用私有仓库的方式&#xff0c;集中管理。 (2) 创建阿里Docker仓库 登录阿里云创建私有仓库 网址&#xff1a;容器镜像服…