学习 `@PreDestroy`:Java EE/Jakarta EE 生命周期回调

学习 `@PreDestroy`:Java EE/Jakarta EE 生命周期回调

  • 前言
    • 1. 什么是 `@PreDestroy`?
    • 2. `@PreDestroy` 的用途
    • 3. 使用 `@PreDestroy` 的条件
    • 4. 代码示例
      • 运行结果:
    • 5. `@PreDestroy` 的调用时机
    • 6. 注意事项
    • 7. 实际应用场景
      • 场景 1:数据库连接管理
      • 场景 2:文件资源释放
    • 8. 总结


前言

在 Java EE(Enterprise Edition)和 Jakarta EE 中,@PreDestroy 是一个非常重要的注解,用于管理对象的生命周期。它允许开发者在对象被容器销毁之前执行一些清理操作,比如释放资源、关闭连接等。本文将详细介绍 @PreDestroy 的用法、适用场景以及注意事项,并通过示例帮助大家更好地理解。


1. 什么是 @PreDestroy

@PreDestroy 是 Java EE/Jakarta EE 提供的一个注解,用于标记一个方法,该方法会在对象被容器销毁之前自动调用。它是对象生命周期回调的一部分,通常与 @PostConstruct 配合使用。

  • @PostConstruct:在对象创建并依赖注入完成后调用。
  • @PreDestroy:在对象被销毁之前调用。

2. @PreDestroy 的用途

@PreDestroy 主要用于执行一些清理工作,例如:

  • 关闭数据库连接。
  • 释放文件或网络资源。
  • 清理缓存或临时数据。
  • 注销监听器或回调。

这些操作可以确保资源被正确释放,避免内存泄漏或其他资源浪费问题。


3. 使用 @PreDestroy 的条件

要正确使用 @PreDestroy,需要满足以下条件:

  1. 方法签名
    • 方法必须没有参数。
    • 方法必须返回 void
    • 方法不能抛出受检异常(checked exceptions)。
  2. 托管对象
    • @PreDestroy 只能用于由容器管理的对象,比如 EJB、CDI Bean、Servlet 等。
    • 如果对象是原型作用域(prototype scope),@PreDestroy 不会被调用。

4. 代码示例

以下是一个简单的示例,展示了如何在 CDI Bean 中使用 @PreDestroy

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class ResourceManager {

    // 模拟资源初始化
    @PostConstruct
    public void init() {
        System.out.println("资源初始化完成...");
    }

    // 业务方法
    public void doWork() {
        System.out.println("正在执行任务...");
    }

    // 清理资源
    @PreDestroy
    public void cleanup() {
        System.out.println("正在清理资源...");
        // 这里可以关闭数据库连接、释放文件资源等
    }
}

运行结果:

  1. 当容器启动并创建 ResourceManager 实例时,init() 方法会被调用,输出:“资源初始化完成…”。
  2. 当调用 doWork() 方法时,输出:“正在执行任务…”。
  3. 当容器关闭或 Bean 被销毁时,cleanup() 方法会被调用,输出:“正在清理资源…”。

5. @PreDestroy 的调用时机

@PreDestroy 方法会在以下情况下被调用:

  • 应用程序关闭时:当应用服务器或容器关闭时,所有托管对象的 @PreDestroy 方法都会被调用。
  • 作用域结束时:对于具有特定作用域的 Bean(如 @RequestScoped@SessionScoped),当作用域结束时,@PreDestroy 方法会被调用。
  • 容器决定销毁对象时:当容器不再需要某个对象时(例如,对象超出作用域或容器资源不足),@PreDestroy 方法会被调用。

6. 注意事项

  1. 原型作用域的 Bean

    • 如果 Bean 是原型作用域(prototype scope),@PreDestroy 不会被调用,因为容器不管理原型 Bean 的生命周期。
  2. 异常处理

    • @PreDestroy 方法不能抛出受检异常,否则可能会导致容器无法正常销毁对象。
  3. 与 Spring 的兼容性

    • 在 Spring 框架中,@PreDestroy 的功能与 Java EE/Jakarta EE 中的一致。Spring 还提供了其他方式来实现类似功能,比如实现 DisposableBean 接口或在 XML 配置中指定 destroy-method

7. 实际应用场景

场景 1:数据库连接管理

在数据库操作类中,可以使用 @PreDestroy 来确保数据库连接被正确关闭。

@ApplicationScoped
public class DatabaseService {

    private Connection connection;

    @PostConstruct
    public void init() {
        // 初始化数据库连接
        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
    }

    @PreDestroy
    public void close() {
        if (connection != null) {
            try {
                connection.close();
                System.out.println("数据库连接已关闭。");
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

场景 2:文件资源释放

在文件操作类中,可以使用 @PreDestroy 来确保文件流被关闭。

@ApplicationScoped
public class FileService {

    private FileInputStream fileInputStream;

    @PostConstruct
    public void init() {
        try {
            fileInputStream = new FileInputStream("data.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    @PreDestroy
    public void cleanup() {
        if (fileInputStream != null) {
            try {
                fileInputStream.close();
                System.out.println("文件流已关闭。");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

8. 总结

@PreDestroy 是 Java EE/Jakarta EE 中非常重要的生命周期回调注解,用于在对象销毁之前执行清理操作。通过合理使用 @PreDestroy,可以确保资源被正确释放,避免内存泄漏和资源浪费。在实际开发中,@PreDestroy 通常与 @PostConstruct 配合使用,分别用于初始化和清理工作。

希望本文能帮助你更好地理解和使用 @PreDestroy!如果有任何问题,欢迎留言讨论!

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

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

相关文章

Linux System V - 消息队列与责任链模式

概念 消息队列是一种以消息为单位的进程间通信机制,允许一个或多个进程向队列中发送消息,同时允许一个或多个进程从队列中接收消息。消息队列由内核维护,具有以下特点: 异步通信:发送方和接收方不需要同时运行&#x…

微信小程序客服消息接收不到微信的回调

微信小程序客服消息,可以接收到用户进入会话事件的回调,但是接收不到用户发送消息的回调接口。需要在微信公众平台,把转发消息给客服的开关关闭。需要把这个开关关闭,否则消息会直接发送给设置的客服,并不会走设置的回…

pycharm社区版有个window和arm64版本,到底下载哪一个?还有pycharm官网

首先pycharm官网是这一个。我是在2025年2月16日9:57进入的网站。如果网站还没有更新的话,那么就往下滑一下找到 community Edition,这个就是社区版了免费的。PyCharm:适用于数据科学和 Web 开发的 Python IDE 适用于数据科学和 Web 开发的 Python IDE&am…

风险价值VaR、CVaR与ES

风险价值VaR、CVaR与ES 一、VaR风险价值1. VaR的定义及基本概念2.VaR的主要性质3.风险价值的优缺点 二、CVaR条件风险价值与ES预期损失1.CVaR的基本概念2.性质3.ES预期损失 一、VaR风险价值 1. VaR的定义及基本概念 20年前,JP的大佬要每天下午收盘后的4:15在桌上看…

老游戏回顾:d2

游戏中玩家创建属于自己的角色,在一片片暗黑大地上奔跑、杀敌、寻宝、成长,最终打败统治各个大陆的黑暗势力,拯救游戏中的各个种族。 《暗黑破坏神II》的制作团队包括编程小组、运动物体制作小组和背景制作小组。游戏设计很大程度上是开放的&…

The Heliosphere 日球层

转自 The Heliosphere - NASA This is an artists concept of our Heliosphere as it travels through our galaxy with the major features labeled. Termination Shock: Blowing outward billions of kilometers from the Sun is the solar wind, a thin stream of electrica…

el-dropdown选中效果

vue2版本 <template><el-dropdown size"mini" command"handleCommand"><span class"el-dropdown-link">{{ selectedOption }}<i class"el-icon-arrow-down el-icon--right"></i></span><el-d…

TOGAF之架构标准规范-信息系统架构 | 应用架构

TOGAF是工业级的企业架构标准规范&#xff0c;信息系统架构阶段是由数据架构阶段以及应用架构阶段构成&#xff0c;本文主要描述信息系统架构阶段中的应用架构阶段。 如上所示&#xff0c;信息系统架构&#xff08;Information Systems Architectures&#xff09;在TOGAF标准规…

【 Avalonia UI 语言国际化 I18n】图文结合教学,保姆级教学,语言国际化就是这么简单(.Net C#)

完整项目地址 github : https://github.com/Crazy-GrowUp/AvaloniaI18nTest/tree/master gitee :https://gitee.com/jack_of_disco/avalonia-i18n-test 0.项目新建 Properties 文件夹 对应的项目配置文件里面就会增加 <Folder Include"Properties\" /> 1.项…

【IoPortDirect】- KRTS C++示例精讲(12)

IoPortDirect示例讲解 文章目录 IoPortDirect示例讲解结构说明代码说明 项目打开请查看【BaseFunction精讲】。 结构说明 IoPortDirect.cpp &#xff1a;源码 其余文件说明请查看【BaseFunction精讲】中的结构说明。 ps : 内核层中的数据、结构体需要一字节对齐&#xff0c;需…

Python——生成AIGC图像

文章目录 一、背景介绍 二、效果图展示 三、完整代码 四、分步解释 五、实用建议 1&#xff09;提示词技巧 2&#xff09;性能优化 3&#xff09;常见问题处理 4&#xff09;扩展功能建议 六、注意事项 1. 硬件要求 2. 法律合规 3. 模型安全 一、背景介绍 AIGC&a…

分巧克力(二分查找)

#include <iostream> using namespace std; int main() {// 请在此输入您的代码int n,k;cin>>n>>k;int N100005;int a[N],b[N];for(int i0;i<n;i){cin>>a[i]>>b[i];}int l1,r1e5;int ans;while(l<r){int midl(r-l)/2;long long cnt0;for(i…

嵌入式经常用到串口,如何判断串口数据接收完成?

说起通信&#xff0c;首先想到的肯定是串口&#xff0c;日常中232和485的使用比比皆是&#xff0c;数据的发送、接收是串口通信最基础的内容。这篇文章主要讨论串口接收数据的断帧操作。 空闲中断断帧 一些mcu&#xff08;如&#xff1a;stm32f103&#xff09;在出厂时就已经在…

大白话实战Gateway

网关功能 网关在分布式系统中起了什么作用?参考下图: 前端想要访问业务访问,就需要知道各个访问的地址,而业务集群服务有很多,前端需要记录非常多的服务器地址,这种情况下,我们需要对整个业务集群做一个整体屏蔽,这个时候就引入Gateway网关,它就是所有服务的请求入…

用大内存主机下载Visual Studio

用一台内存达到128G的主机下载Visual Studio 2022&#xff0c;用的是公司网络。下载速度让我吃了一惊&#xff0c;没人用网络了&#xff1f;还是网站提速了&#xff1f;以前最大只能达到5MB/秒。记录这段经历&#xff0c;是用来分析公司网络用的......

【C++语言】string 类

一、为什么要学习 string 类 C语言中&#xff0c;字符串是以 “\0” 结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些 str 系列的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合 OOP 的思想&#xff0c;而且底层空间需…

深度学习-123-综述之AI人工智能与DL深度学习简史1956到2024

文章目录 1 AI与深度学习的简史1.1 人工智能的诞生(1956)1.2 早期人工神经网络(1940-1960年代)1.3 多层感知器MLP(1960年代)1.4 反向传播(1970-1980年代)1.5 第二次黑暗时代(1990-2000年代)1.6 深度学习的复兴(21世纪末至今)1.6.1 CNN卷积神经网络(1980-2010)1.6.2 RNN递归神经…

解决本地模拟IP的DHCP冲突问题

解决 DHCP 冲突导致的多 IP 绑定失效问题 前言 续接上一篇在本机上模拟IP地址。 在实际操作中&#xff0c;如果本机原有 IP&#xff08;如 192.168.2.7&#xff09;是通过 DHCP 自动获取的&#xff0c;直接添加新 IP&#xff08;如 10.0.11.11&#xff09;可能会导致 DHCP 服…

基于Llama 3.2-Vision的医学报告生成

记录运用大模型解决医学报告实例&#xff0c;仅介绍本地调用的情况。 前情提要 已安装 Python 显存不少于8G&#xff08;8G设备上测试成功&#xff0c;其他环境可以自行测试&#xff09;。 需要安装Ollama (Ollama 是一个允许在本地运行多模态模型的平台)。 方式1&#xff1…

DeepSeek预测25考研分数线

25考研分数马上要出了。 目前&#xff0c;多所大学已经陆续给出了分数查分时间&#xff0c;综合往年情况来看&#xff0c;每年的查分时间一般集中在2月底。 等待出成绩的日子&#xff0c;学子们的心情是万分焦急&#xff0c;小编用最近爆火的“活人感”十足的DeepSeek帮大家预…