Spring从零开始学使用系列(四)之@PostConstruct和@PreDestroy注解的使用

  如果各位老爷觉得可以,请点赞收藏评论,谢谢啦!!

  文章中涉及到的图片均由AI生成

  公众号在最下方!!!

目录

1. 介绍

1.1 @PostConstruct概述

1.2 @PreDestroy概述

2. 基本用法

2.1 注册CommonAnnotationBeanPostProcessor

2.2 使用@PostConstruct注解的方法

2.3 使用@PreDestroy注解的方法

3. 使用场景

3.1 资源管理

3.2 缓存管理

3.3 初始化复杂对象

4. 注意事项

4.1 线程安全

4.2 异常处理

4.3 使用限制

4.4 调用初始化模板和方法

4.5 初始化顺序和Bean的生命周期

5. 结论

1. 介绍

        在Spring框架中,@PostConstruct和@PreDestroy注解是用于管理Bean生命周期的重要工具。这些注解提供了一种简洁的方式,在Bean的初始化和销毁阶段执行特定的逻辑,从而增强了应用程序的灵活性和可维护性。

1.1 @PostConstruct概述

        @PostConstruct注解用于在Bean初始化完成后立即执行特定的方法。这通常用于在依赖注入完成后进行一些初始化操作,例如分配资源或预填充缓存。

1.2 @PreDestroy概述

        @PreDestroy注解用于在Bean销毁之前执行特定的方法。这通常用于在Bean被销毁之前进行一些清理操作,例如释放资源或清空缓存。

        这些注解是在JSR-250规范中定义的,最初是作为Java标准库的一部分引入的。从JDK 9开始,这些注解被移除并移至Jakarta EE中。如果需要使用这些注解,需要在项目中引入jakarta.annotation-api依赖。

2. 基本用法

2.1 注册CommonAnnotationBeanPostProcessor

        要使用@PostConstruct和@PreDestroy注解,首先需要在Spring配置中注册CommonAnnotationBeanPostProcessor(老版本是不需要的,因为jdk8自带@PostConstruct注解),这样Spring才能识别并处理这些注解:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;

@Configuration
public class AppConfig {
    
    @Bean
    public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {
        return new CommonAnnotationBeanPostProcessor();
    }
}
2.2 使用@PostConstruct注解的方法

        @PostConstruct注解用于在Bean初始化完成后执行特定的方法。以下是一个示例,展示如何在Bean初始化完成后填充缓存:

import jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class CachingMovieLister {

    @PostConstruct
    public void populateMovieCache() {
        // 在初始化时填充电影缓存...
        System.out.println("Movie cache populated upon initialization");
    }
}
2.3 使用@PreDestroy注解的方法

        @PreDestroy注解用于在Bean销毁之前执行特定的方法。以下是一个示例,展示如何在Bean销毁之前清空缓存:

import jakarta.annotation.PreDestroy;
import org.springframework.stereotype.Component;

@Component
public class CachingMovieLister {

    @PreDestroy
    public void clearMovieCache() {
        // 在销毁时清空电影缓存...
        System.out.println("Movie cache cleared upon destruction");
    }
}

3. 使用场景

3.1 资源管理

        在许多应用程序中,Bean在初始化时可能需要分配一些资源(如数据库连接、文件句柄等),并在销毁时释放这些资源。@PostConstruct和@PreDestroy注解可以帮助我们在这些关键点上执行必要的操作,防止资源泄漏。

3.2 缓存管理

        在某些应用程序中,可能需要在Bean初始化时预填充缓存,并在销毁时清空缓存,以确保数据一致性和内存有效利用。

3.3 初始化复杂对象

        有时Bean依赖于其他资源进行初始化,@PostConstruct可以确保在所有依赖注入完成后执行初始化逻辑。

import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ComplexInitializer {

    @Autowired
    private SomeDependency dependency;

    private ComplexObject complexObject;

    @PostConstruct
    public void init() {
        complexObject = new ComplexObject(dependency);
        System.out.println("ComplexObject initialized with dependency");
    }

    public ComplexObject getComplexObject() {
        return complexObject;
    }
}

4. 注意事项

4.1 线程安全

        在使用@PostConstruct和@PreDestroy注解的方法中,确保线程安全是非常重要的。由于Spring容器可能会在多个线程中并发地管理Bean的生命周期,方法中的代码应避免共享可变状态,或者使用同步机制保护共享资源。

4.2 异常处理

        在这些方法中处理异常是非常关键的。如果在@PostConstruct方法中抛出异常,Spring容器可能会终止Bean的初始化过程。如果在@PreDestroy方法中抛出异常,可能会导致资源泄漏。建议在这些方法中捕获并记录异常,确保应用程序的稳定性。

@PostConstruct
public void initialize() {
    try {
        // 初始化逻辑
    } catch (Exception e) {
        // 处理异常
        e.printStackTrace();
    }
}

@PreDestroy
public void cleanup() {
    try {
        // 清理逻辑
    } catch (Exception e) {
        // 处理异常
        e.printStackTrace();
    }
}
4.3 使用限制

        @PostConstruct和@PreDestroy注解的方法不能是final或static的,因为Spring需要通过代理机制来管理Bean的生命周期,final或static方法无法被代理。此外,这些方法不能有参数,并且必须是无返回值的void方法。

4.4 调用初始化模板和方法

        在某些复杂的场景中,可能需要在多个Bean中复用相同的初始化或清理逻辑。可以通过定义一个模板方法,并在具体Bean中调用该模板方法来实现代码复用。

public abstract class AbstractInitializer {

    @PostConstruct
    public void postConstruct() {
        init();
    }

    @PreDestroy
    public void preDestroy() {
        destroy();
    }

    protected abstract void init();
    protected abstract void destroy();
}

@Component
public class ConcreteInitializer extends AbstractInitializer {

    @Override
    protected void init() {
        // 具体的初始化逻辑
        System.out.println("ConcreteInitializer initialized");
    }

    @Override
    protected void destroy() {
        // 具体的清理逻辑
        System.out.println("ConcreteInitializer destroyed");
    }
}

        通过这种方式,可以在多个Bean中共享相同的初始化和清理逻辑,减少代码重复,提高代码的可维护性。

4.5 初始化顺序和Bean的生命周期

        在Spring中,Bean的初始化顺序可能会导致在使用@PostConstruct注解时调用其他Bean出现问题。具体来说,如果一个Bean在其@PostConstruct方法中依赖于另一个尚未初始化的Bean,就会导致初始化失败。为了避免这种情况,应该确保依赖的Bean在当前Bean之前初始化。

@Service
public class MyService {

    @Autowired
    private AnotherService anotherService;

    @PostConstruct
    public void init() {
        anotherService.performAction();
    }
}

@Service
public class AnotherService {

    public void performAction() {
        System.out.println("Action performed");
    }
}

        在上面的示例中,如果AnotherService尚未初始化而MyService已经在其@PostConstruct方法中调用了anotherService的方法,则会导致错误。

解决方法:

  1. 确保Bean的初始化顺序:可以通过在Spring配置文件中明确指定Bean的依赖关系,确保依赖的Bean在当前Bean之前初始化。

  2. 使用@DependsOn注解:可以使用@DependsOn注解明确指定Bean的初始化顺序

  3. 在Bean的生命周期中处理依赖:了解Bean的生命周期,并在正确的生命周期阶段处理Bean的依赖关系。Spring的Bean生命周期包括实例化、属性注入、初始化和销毁等阶段。@PostConstruct方法在属性注入之后、初始化之前调用,因此应确保在此阶段所有依赖的Bean都已准备好。

5. 结论

        在Spring框架中,@PostConstruct和@PreDestroy注解为开发者提供了一种简洁而有效的方式来管理Bean的生命周期。这些注解能够确保在Bean初始化后执行必要的设置操作,并在Bean销毁前进行必要的清理操作,从而提升了应用程序的健壮性和可维护性。

        通过本文的详细介绍和示例,我们探讨了以下内容:

  1. @PostConstruct和@PreDestroy的概述:理解这些注解在Spring框架中的作用和意义。
  2. 基本用法:如何在Spring配置中注册CommonAnnotationBeanPostProcessor,以及如何在实际Bean中使用这些注解。
  3. 使用场景:通过具体示例展示了在资源管理、缓存管理和初始化复杂对象中的应用。
  4. 注意事项:强调了线程安全、异常处理、使用限制、调用初始化模板和方法、以及Bean的初始化顺序和生命周期管理的重要性。

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

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

相关文章

微信小程序基础 -- 小程序UI组件(5)

小程序UI组件 1.小程序UI组件概述 开发文档:https://developers.weixin.qq.com/miniprogram/dev/framework/view/component.html 什么是组件: 组件是视图层的基本组成单元。 组件自带一些功能与微信风格一致的样式。 一个组件通常包括 开始标签 和 结…

HTTP的由来以及发展史

HTML&HTML5的学习探索 01、Html的由来和发展史 01-01、Html的由来 HTML的英文全称是 Hypertext Marked Language,即超文本标记语言。HTML是由Web的发明者 Tim Berners-Lee(蒂姆伯纳斯李)于1990年创立的一种标记语言, 他是万…

从程序被SQL注入来MyBatis 再谈 #{} 与 ${} 的区别

缘由 最近在的一个项目上面,发现有人在给我搞 SQL 注入,我真的想说我那么点资源测试用的阿里云服务器,个人估计哈,估计能抗住他的请求。狗头.png 系统上面的截图 数据库截图 说句实在的,看到这个之后我立马就是在…

《Python源码剖析》之pyc文件

前言 前面我们主要围绕pyObject和pyTypeObject聊完了python的内建对象部分,现在我们将开启新的篇章—python虚拟机,将聚焦在python的执行部分,搞懂从“代码”到“执行”的过程。开启新的篇章之前,你也许会有一个疑惑:我…

VLAN高级特性

1.VLAN聚合 (1)VLAN聚合产生的技术背景 (2)VLAN聚合概述 (3)VLAN聚合的原理 多个Sub-VLAN共享一个网关地址,节约了子网网络地址、子网定向广播地址、子网缺省网关地址,且各Sub-VLAN…

C#调用HttpClient.SendAsync报错:System.Net.Http.HttpRequestException: 发送请求时出错。

C#调用HttpClient.SendAsync报错:System.Net.Http.HttpRequestException: 发送请求时出错。 var response await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);问题出在SSL/TLS,Windows Server 2012不支持…

MybatisPlus中自定义sql

背景 在开发过程中,可能会出现除了where条件,其它sql比较复杂,这时候就需要用到自定义sql了。 问题 如:用户状态为正常的数据年龄加一(所有用户年龄加一) 数据库中sql: UPDATE USER SET…

【Linux】TCP协议【下一】{三次握手/四次挥手的深度解读==状态变化}

文章目录 本篇知识需要有TCP协议【中】的知识!详情点击👇1.测试一:服务器start函数不定义任何行为(不调用accept)的三次握手状态变化int listen(int sockfd, int backlog);的backlog参数全连接队列当全连接队列已满&am…

异方差的Stata操作(计量114)

以数据集 nerlove.dta 为例,演示如何在 Stata 中处理异方差。 此数据集包括以下变量: tc ( 总成本 ) ; q ( 总产量 ) ; pl ( 工资率 ) ; pk ( 资本的使用成本 ) ; pf ( 燃料价格 ) ; …

Cyber Weekly #8

赛博新闻 1、微软召开年度发布会Microsoft Build 2024 本周(5.22)微软召开了年度发布会,Microsoft Build 2024,发布了包括大杀器 Copilot Studio 在内的 50 项更新。主要包括: 硬件层面:与英伟达 & A…

Python的pip配置、程序运行、生成exe文件

一、安装Python 通过官网下载对应的版本,安装即可。 下载地址:Download Python | Python.org Python标准库查看(Python自带库) Python 标准库文档 安装Python的时候,如果选第二个自定义安装要记得勾选安装pip 二、…

go-zero 实战(4)

中间件 在 userapi 项目中引入中间件。go项目中的中间可以处理请求之前和之后的逻辑。 1. 在 userapi/internal目录先创建 middlewares目录,并创建 user.go文件 package middlewaresimport ("github.com/zeromicro/go-zero/core/logx""net/http&q…

返回枚举类给前端

1. 前言 在实际开发过程中,前端的下拉框或者单选按钮的内容通常的需要和后端匹配的,故一般会由后端将下拉框的内容或单选框的内容传给前端,而这些内容在后端一般是由枚举类存储的,如果后端直接返回枚举类,返回结果将会…

民国漫画杂志《时代漫画》第24期.PDF

时代漫画24.PDF: https://url03.ctfile.com/f/1779803-1248635000-177187?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了,截止1937年6月战争来临被迫停刊共发行了39期。 ps: 资源来源网络!

基于YOLOv8的车牌检测与识别(CCPD2020数据集)

前言 本篇博客主要记录在autodl服务器中基于yolov8实现车牌检测与识别,以下记录实现全过程~ yolov8源码:GitHub - ultralytics/ultralytics: NEW - YOLOv8 🚀 in PyTorch > ONNX > OpenVINO > CoreML > TFLite 一、环境配置 …

怎么在网上赚点零花钱?分享十个正规的赚钱兼职平台

亲爱的朋友们,大家好!今天要和大家聊聊一个让人兴奋的话题——网上赚钱。在这个互联网飞速发展的时代,网上赚钱已经不再是遥不可及的梦想。如果你正想在网上赚点零花钱,那么这篇文章你可不能错过! 在这个信息爆炸的时代…

ASP.NET 代码审计

ASP.NET 官方文档 名词解释 IIS(Internet Information Services) IIS 是微软开发的一款 Web 服务器软件,用于在 Windows 服务器上托管和提供Web应用程序和服务。它支持 HTTP、HTTPS、FTP、SMTP 等多种协议,主要用于&#xff1a…

HTML与CSS的学习

什么是HTML,CSS&#xff1f; HTML(HyperText Markup Language):超文本标记语言。 超文本:超越了文本的限制&#xff0c;比普通文本更强大。除了文字信息&#xff0c;还可以定义图片、音频、视频等 标记语言:由标签构成的语言 >HTML标签都是预定义好的。例如:使用<a>…

Jupyter Lab 软件安装与使用

软件简介 Jupyter Lab 软件是一个基于web 的交互式开发环境&#xff0c;集成了代码编辑器、终端、文件管理器等功能&#xff0c;使得开发者可以在一个界面中完成各种任务。JupyterLab是Jupyter Notebook的全面升级&#xff0c;是一个集文本编辑器、终端以及各种个性化组件于一…

STL库 —— unordered_set与unordered_map的封装

这里要对 unordered_set 与 unordered_map 进行封装&#xff0c;封装时使用的是上一篇中学的 HashBucket 。不仅要完成封装&#xff0c;同时要写入迭代器。 一、HashBucket 的修改 1.1 节点的修改 T 首先来认识一下使用 unordered_set 和 ordered_map 时的区别&#xff1a; …