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

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 {@Beanpublic CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor() {return new CommonAnnotationBeanPostProcessor();}
}
2.2 使用@PostConstruct注解的方法

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

import jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Component;@Component
public class CachingMovieLister {@PostConstructpublic 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 {@PreDestroypublic 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 {@Autowiredprivate SomeDependency dependency;private ComplexObject complexObject;@PostConstructpublic 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 {@PostConstructpublic void postConstruct() {init();}@PreDestroypublic void preDestroy() {destroy();}protected abstract void init();protected abstract void destroy();
}@Component
public class ConcreteInitializer extends AbstractInitializer {@Overrideprotected void init() {// 具体的初始化逻辑System.out.println("ConcreteInitializer initialized");}@Overrideprotected void destroy() {// 具体的清理逻辑System.out.println("ConcreteInitializer destroyed");}
}

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

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

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

@Service
public class MyService {@Autowiredprivate AnotherService anotherService;@PostConstructpublic 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的初始化顺序和生命周期管理的重要性。

相关文章:

  • 化学中的不确定性。
  • 人工智能+量子计算:飞跃现实边界还是科技幻想?
  • java网络:过滤器修改请求头
  • 一、Elasticsearch介绍与部署
  • 【知识拓展】LocalTunnel-高性价比的内网穿透工具(2)
  • matplotlib latex表格
  • 每日一题---有效的括号问题
  • 双指针用法练习题(2024/5/26)
  • 通过unsplash引入图片素材
  • 小程序的深层了解
  • React 如何自定义 Hooks
  • Win11禁用数字强制签名:解放硬件选择,自由安装应用
  • CasaOS系统玩客云安装内网穿透工具实现无公网IP远程访问
  • 内存函数详解,包含部分字符串函数
  • 深入理解python列表与字典:数据结构的选择与性能差异
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 【知识碎片】第三方登录弹窗效果
  • Intervention/image 图片处理扩展包的安装和使用
  • Javascript设计模式学习之Observer(观察者)模式
  • Java精华积累:初学者都应该搞懂的问题
  • java小心机(3)| 浅析finalize()
  • Phpstorm怎样批量删除空行?
  • Python语法速览与机器学习开发环境搭建
  • Swift 中的尾递归和蹦床
  • vue-cli在webpack的配置文件探究
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 好的网址,关于.net 4.0 ,vs 2010
  • 解析带emoji和链接的聊天系统消息
  • 盘点那些不知名却常用的 Git 操作
  • 前端设计模式
  • 巧用 TypeScript (一)
  • 追踪解析 FutureTask 源码
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 移动端高清、多屏适配方案
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • # Maven错误Error executing Maven
  • # 利刃出鞘_Tomcat 核心原理解析(七)
  • #07【面试问题整理】嵌入式软件工程师
  • #QT 笔记一
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (函数)颠倒字符串顺序(C语言)
  • (理论篇)httpmoudle和httphandler一览
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (十) 初识 Docker file
  • (四)事件系统
  • (算法)Game
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .net core webapi 大文件上传到wwwroot文件夹
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET 某和OA办公系统全局绕过漏洞分析