Spring中@PostConstruct注解的使用

1.描述

1.1 背景

        最近在做一个系统交互日志模块,要监控一个http请求,并记录请求与响应日志。项目中使用RestTemplate来发送http请求,所以打算给RestTemplate设置拦截器,来进行自定义操作。但是,只对当前类生效,不能影响到其他RestTemplate的使用。然而,在改造过程中,遇到了bean为空的情况,经排查,是因为在构造方法中使用这个bean给RestTemplate初始化拦截器操作时,bean的依赖注入还未完成,出现了空指针异常。那么是不是有一种方式,在bean依赖注入完成之后,再执行初始化呢?当然有,@PostConstruct就能解决这个问题,比较推荐这种方式。

1.2 注意事项

关于bean的使用,我们要注意:

(1)要注意bean的加载与使用顺序:如果使用该bean时,bean为空,无非就俩种情况:a:未被spring管理、b:使用该bean时,该bean的依赖注入还未完成。

(2)要将bean交给spring管理,通过依赖注入的方式去使用:如果该bean中,依赖了别的bean。那么要将该bean交给spring管理,且使用该bean时,要通过依赖注入的方式去拿,而不要去new。

2.@PostConstruct简单介绍

2.1 简介:

   @PostConstruct 是 Java 中的一个注解,用于在 Spring 框架中指定初始化方法。当一个 Bean 被实例化之后,如果该 Bean 类中存在用 @PostConstruct 注解的方法,那么该方法会在依赖注入(DI)完成后被自动调用,用于执行一些自定义的初始化操作。

2.2 @PostConstruct的作用

  • 初始化操作:在bean的依赖注入完成后,执行一些初始化操作。
  • 资源准备:比如数据库连接、文件系统访问等,需要在依赖注入完成后才能进行。
  • 状态验证:可以检查bean的依赖是否正确注入,或者做一些状态的验证。

2.3  @PostConstruct 的一些关键点:

  • @PostConstruct 注解用于在依赖注入完成后执行 Bean 的初始化逻辑。
  • 一个类中只能有一个方法用 @PostConstruct 注解。
  • 被 @PostConstruct 注解的方法不能有参数,并且返回类型必须为 void
  • 被 @PostConstruct 注解的方法通常应该是非静态的,但如果它所在类是单例模式,那么静态方法也可以被注解。

2.4 举例

(1)执行顺序:构造函数被调用——>@PostConstruct 方法被调用

import javax.annotation.PostConstruct;public class MyClass {private String message;public MyClass() {System.out.println("构造函数被调用");}@PostConstructpublic void init() {System.out.println("@PostConstruct 方法被调用");message = "Hello, World!";}public String getMessage() {return message;}
}

        在这个例子中,我们有一个名为 MyClass 的类,它有一个私有成员变量 message。我们在构造函数中打印一条消息,然后在 init 方法上使用 @PostConstruct 注解。当 Spring 容器创建 MyClass 的实例并完成依赖注入后,它会调用 init 方法来初始化 message 变量。

 (2)初始化时从文件系统加载一些配置数据:

import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;@Service
public class ConfigurationService {private String configData;@PostConstructpublic void loadConfigData() {try (BufferedReader reader = new BufferedReader(new FileReader("config.properties"))) {StringBuilder sb = new StringBuilder();String line;while ((line = reader.readLine()) != null) {sb.append(line).append("\n");}configData = sb.toString();System.out.println("Configuration data loaded.");} catch (IOException e) {throw new RuntimeException("Failed to load configuration data", e);}}public String getConfigData() {return configData;}
}

        在这个例子中,loadConfigData 方法被@PostConstruct注解所标记。当Spring IoC容器创建并完成ConfigurationService Bean的依赖注入后,这个方法就会被自动调用。 

        此外,一个类中可以有多个带有@PostConstruct注解的方法,但是通常建议只使用一个这样的方法来保持代码的清晰性和可维护性。如果需要更复杂的初始化逻辑,考虑使用InitializingBean接口或者init-method属性。

注:Spring bean的加载注入顺序大体是构造方法 -> 依赖注入 -> @PostConstruct注解的方法

3.扩展:bean的加载流程

Spring的bean加载和注入过程主要分为以下几个步骤:

  • 加载BeanDefinition

    • Spring容器通过扫描类路径、解析注解或读取XML配置文件,加载bean定义。
  • 注册BeanDefinition

    • 将加载的bean定义注册到BeanDefinitionRegistry中。
  • 创建Bean实例

    • 容器根据bean定义创建bean实例。
  • 属性填充

    • 容器会根据bean定义中的属性值,填充bean实例的属性。
  • 依赖注入

    • 容器会解析bean定义中的依赖关系,并注入相应的bean或值。
  • 调用@PostConstruct方法

    • 在依赖注入完成后,调用bean的@PostConstruct方法。
  • 初始化Bean

    • 容器会调用bean的初始化方法(如果有),比如实现了InitializingBean接口的afterPropertiesSet方法。
  • Bean准备就绪

    • 所有初始化操作完成后,bean就可以被使用了。

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

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

相关文章

2024 暑假友谊赛 2

2024 暑假友谊赛 2 2024.7.20 9:00————12:00 过题数3/9 补题数4/9 CodeForces 1150B CodeForces 1332D CodeForces 1503B AtCoder arc134_b AtCoder abc278_d AtCoder abc216_f CodeForces 1012B CodeForces 1328E AtCoder abc344_f A - Tiling Challenge 题解&#xff…

前端监听浏览器关闭事件

在 beforeunload 事件中,无法直接监听离开按钮的点击事件,也不能为 event.currentTarget 添加 close 事件监听器来获取离开按钮的相关事件。 beforeunload 事件主要用于在页面即将卸载(刷新或关闭)时进行一些必要的处理&#xff0…

Java文件IO操作知识点

关于文件 关于IO的定义 I:input输入 O:output输出,这是一套人为规定的规则,下面这个图方便我们理解输入输出的定义,统一以CPU为基准 在操作系统中其实把很多的资源都抽象成文件,我们在这里所说的文件就是"狭义"文件,平时保存在硬盘上的文件, 文件夹也是一种文件,我们…

mysql的数据往hive进行上报时怎么保证数据的准确性和一致性

在将MySQL的数据往Hive进行上报时,确保数据的准确性和一致性可以通过下面一系列步骤来实现 一、准备工作 环境配置: 确保MySQL和Hive环境已经安装并配置好,且都处于可运行状态。检查Hadoop集群(Hive通常运行在Hadoop之上&#x…

「iOS」自定义cell与cell的复用

iOS学习 前言一:TableView协议二:cell的复用Cell的复用原理自定义cell总结 前言 UITableView是iOS开发中不可或缺的一部分,它是苹果iOS SDK提供的一种用于展示数据列表的视图控件。我们对其中的cell进行自定义,即可得到我们需要的…

Python 实现股票指标计算——BBI

BBI (Bull And Bear lndex) - 多空指标 1 公式 3日均价 3日收盘价之和 / 36日均价 6日收盘价之和 / 612日均价 12日收盘价之和 / 1224日均价 24日收盘价之和 / 24BBI (3日均价 6日均价 12日均价 24日均价) / 4 2 数据准备 我们以科创50指数 000688 为例&#xff0c…

Qt 学习第一天:安装VS和Qt

本人更换了一台新的电脑,使用联想电脑管家传输文件后没有安装VS,导致出现了以下问题: 疯狂查资料问人。弄了一个晚上加上午一个多小时之后,还是决定删掉原来的文件夹,重新下载一个 一、安装VS(Visual Stud…

肿瘤病人的护理

一、肿瘤病人的心理护理 肿瘤患者往往面临巨大的心理压力和恐惧,心理护理至关重要。 倾听与理解 耐心倾听患者的倾诉,让他们表达内心的担忧、恐惧和不安。例如,一位肺癌患者可能会担心治疗效果和家庭经济负担,护理人员要给予充分的…

Aurora MySQL 负载突增应对策略与优化方案

在面对 Aurora MySQL 负载突增的情况下,我们需要深入理解其工作原理,并探讨可行的优化方案。本文将详细分析 Aurora MySQL 的负载均衡机制,解读性能监控指标,并提出几种可能的解决方案,包括已实施的措施和未来的优化方向。 1. Aurora MySQL 的负载均衡机制 Aurora MySQL…

简单工厂模式、工厂模式和抽象工厂模式的区别

简单工厂模式、工厂模式和抽象工厂模式都是创建型设计模式,它们之间在目的、实现方式和适用场景上存在显著的区别。以下是对这三种模式的详细比较: 一、定义与目的 简单工厂模式(Simple Factory Pattern) 定义: 简单工…

算法项目报告:物流中的最短路径问题

问题描述 物流问题 有一个物流公司需要从起点A到终点B进行货物运输,在运输过程中,该公司需要途径多个不同的城市,并且在每个城市中都有一个配送站点。为了最大程度地降低运输成本和时间,该公司需要确定经过哪些配送站点&#xff…

Android:requestLayout、invalidate 和 postInvalidate 的区别

提醒:下面源码来自SDK里Android-34版本 一、requestLayout 点击查看requestLayout官网文档 1.1 requestLayout方法源码 /*** Call this when something has changed which has invalidated the* layout of this view. This will schedule a layout pass of the v…

Java:RestTemplate返回值报错LinkedHashMap cannot be cast

问题描述 使用SringBoot提供的RestTemplate发起http请求,类型转换成了LinkedHashMap DataEntity result restTemplate.getForObject(url, DataEntity.class);报错信息如下 java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.demo.…

跟着GPT学设计模式之模板模式

你好,这里是codetrend专栏“跟着GPT学设计模式”。 说明 提示词: 对模板模式进行定义说明,优缺点说明。 模板模式,全称是模板方法设计模式,英文是 Template Method Design Pattern。模板模式是一种行为型设计模式,它定…

watch监听vue2与vue3的写法

watch的属性值 handler:回调函数, 即监听到变化时应该执行的函数,可以是单独的函数或带有 immediate 和 deep 属性的对象watch: {someProperty: function(newVal, oldVal) {// 处理逻辑}}deep: 其值是true或false, 当属性值是对象或数组时,深度观察会监…

C++ :友元类

友元类的概念和使用 (1)将类A声明为B中的friend class后,则A中所有成员函数都成为类B的友元函数了 (2)代码实战:友元类的定义和使用友元类是单向的 (3)友元类是单向的,代码实战验证 互为友元类 (1)2个类可以互为友元类,代码实战…

DP讨论——组合模式

学而时习之,温故而知新。 组合模式 和代理模式相比 和代理模式相比,有点类似。引用类和被引用类都继承于同一个接口类。 但是感觉组合模式是对代理模式的更加丰富化(升级版、超进化),集合化或者说聚合化。 组合模…

高并发小结

高并发是指系统能够处理大量的并发请求的能力。处理高并发问题需要从多个层面进行优化,包括架构设计、代码优化、数据库优化和运维管理等。以下是一些处理高并发的关键技术和方法: 1. 架构设计 分布式架构:将系统功能分解为多个独立的服务&…

linux学习笔记整理: 关于linux:Redis数据库 2024/7/20;

Redis数据库: 自理解: 通过Map(多层字典类型)进行存储查找资源,key为字符串,value可为多种类型; Redis介绍 Redis是一种开放源代码(BSD许可)的内存中数据结构存储,用作数据库,缓存和消息代理。Redis提供数据结构,例如字…

tmp - configmap动态更新配置?

# 这是刚刚更新过的configmaps controlplane $ k describe configmaps nginx-conf Name: nginx-conf Namespace: default Labels: <none> Annotations: <none> Data nginx.conf: ---- user nginx; worker_processes 1; events { worker_co…