Spring Environment 注入引起NPE问题排查

文章目录

        • 背景
        • 原因分析
          • 1)Spring Aware Bean 是什么?
          • 2)从 Spring Bean 的生命周期入手
        • 解决方案

背景

写业务代码遇到使用 Spring Environment 注入为 null 的情况,示例代码有以下两种写法,Environment 实例都无法注入成功,均为 null。

  • 写法一:直接在业务 Bean 中注入 Environment 类
public class IPayInstitutionManager {@Autowireprivate Environment environment;public IPayInstitutionManager() {log.info("IPayInstitutionManager start to init...");log.info("IPayInstitutionManager environment:{}", environment);log.info("testPrivate:{}", environment.getProperty("test.key"));init();}
}
  • 写法二:使用 EnvironmentAware
public class IPayInstitutionManager implements EnvironmentAware {private Environment environment;@Overridepublic void setEnvironment(Environment environment) {this.environment = environment;log.info("IPayInstitutionManager#setEnvironment environment:{}", environment);log.info("IPayInstitutionManager#setEnvironment value:{}", environment.getProperty("test.key"));}public IPayInstitutionManager() {log.info("IPayInstitutionManager start to init...");log.info("IPayInstitutionManager environment:{}", environment);log.info("testPrivate:{}", environment.getProperty("test.key"));init();}
}
原因分析
1)Spring Aware Bean 是什么?

Aware 即”察觉的,注意到的,感知的”,xxxAware 也就是对xxx感知的。Spring 的依赖注入使业务 Bean 对 Spring 容器的存在是没有意识的,但有时候业务 Bean 需要对 Spring 容器有感知,能使用 Spring 容器内置的组件(如 ApplicationContext、BeanFactory 等)。就出现了以下 Aware Bean(具体使用方法不再简介):

  • ApplicationContextAware:获得当前应用上下文
  • EnviromentAware:获得环境变量
  • BeanNameAware:获取容器中bean名称
  • BeanFactoryAware:获得bean工厂
2)从 Spring Bean 的生命周期入手

上面两个例子很容易猜想到 IPayInstitutionManager 进行实例化调用其构造方法过程中,environment 并未执行初始化,以写法二从启动日志中可验证:IPayInstitutionManager 构造函数先于 environment 实例化

在这里插入图片描述

回到 Bean 的生命周期,如下图所示:

在这里插入图片描述

很明显,IPayInstitutionManager 调用构造方法实例化时,Environment 并未完成初始化(图中 EnvironmentAware.setEnvironment 结点)。即若 Spring 未进行 EnvironmentAware.setEnvironment 回调前,Environment 并不能使用,这也是为什么像 Environment、ApplicationContext 等 Spring 内部组件不能直接 @Autowire 注入的原因,必须要实现 Aware Bean

解决方案

结合 Bean 生命周期图,如果要在代码中使用 Environment 等 Spring 组件时,时机要晚于图中 BeanPostProcessor.postProcessBeforeInitialization 方法执行时机即可,比如使用 @PostConstruct 注解,实现 InitializingBean 接口等。这里给出一个示例:

public class IPayInstitutionManager implements EnvironmentAware, InitializingBean {private Environment environment;@Overridepublic void setEnvironment(Environment environment) {this.environment = environment;}@Overridepublic void afterPropertiesSet() {log.info("testPrivate:{}", environment.getProperty("test.key")); // 正常输出init();}
}

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

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

相关文章

Megatron模型并行研究

Megatron模型并行研究 1. 技术调研 a. Megatron-LM Megatron-LM针对的是特别大的语言模型,使用的是模型并行的训练方式。但和普通的模型并行不同,他采用的其实是张量并行的形式,具体来说就是将一个层切开放到不同的GPU上,属于层…

Java中升级属性复制转换功能

前言 在java中,经常碰到bean之间的转换,诸如Entity转VO,Entity转DTO等等,这时,经常会碰到这样一种情况,VO和DTO里面有一个字段都是来源于Entity里面,但是属性名称和属性类型都不一样,虽然转换逻辑一致但是我们还是只能手动转换,这时如果我在代码中手动转换会出现很多多…

基于SSM的旅游网站设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

设计模式:循序渐进走入工厂模式

文章目录 前言一、引入二、简单工厂模式1.实现2.优缺点3.扩展 三、工厂方法模式1.实现2.优缺点 四、抽象工厂模式1.实现2.优缺点3.使用场景 五、模式扩展六、JDK源码解析总结 前言 软件设计模式之工厂模式。 一、引入 需求:设计一个咖啡店点餐系统。 设计一个咖啡类…

设计模式-门面模式

设计模式专栏 模式介绍模式特点应用场景门面模式和代理模式的区别代码示例Java实现门面模式Python实现门面模式 门面模式在spring中的应用 模式介绍 门面模式是一种常用的软件设计模式,也称为外观模式。它提供了一个高层次的接口,将一个子系统的外部与内…

卡通动漫AI绘画视频风格化AI智能PR插件StyleX免费下载

带有AI的视频风格化工具PR AI智能绘画插件。将视频转换为卡通、绘图、绘画、半色调和许多其他风格。 性能高度依赖GPU,一些旧的GPU卡(2012年之前)不受支持。 StyleX是一款先进的视频风格化工具,采用AI技术,它不仅可以将…

代码随想录第三十八天(一刷C语言)|零钱兑换II组合总数和 IV

创作目的:为了方便自己后续复习重点,以及养成写博客的习惯。 一、零钱兑换II 思路:参考carl文档 1、确定dp数组以及下标的含义:凑成总金额j的货币组合数为dp[j]。 2、确定递推公式:dp[j] 就是所有的dp[j - coins[i…

仿悬赏猫任务平台源码 悬赏任务系统源码 带支付接口

源码介绍 最新仿悬赏猫任务平台源码 悬赏任务系统源码 带支付接口, 全新开发悬赏任务系统,功能齐全,包含接任务,发布任务, 店铺关注,置顶推荐,排行榜,红包大厅,红包抽奖…

深信服AF防火墙升级步骤(简单粗暴)

设备当前版本:AF8.0.75 升级升级后版本:AF8.0.85 官方发行:内容比较多,找设备当前版本在不在支持升级的列表即可 8.0.75是可以直接升到8.0.85的 升级前注意事项: 升级是需要重启设备的,会断网&#xff…

两种方法解决win10开机慢,经验分享

方法一: 1、按快捷键“winR”打开 运行窗口。 2、这时候输入“msconfig”后 ,点击“确定”或者按“ENTER”键。 3、这时候会打开一个名为“系统配置”的窗口, 在“常规”选项框下 勾选“有选择的启动”下的“加载系统服务”和“加载启动项”。…

C语言的scanf输入函数的介绍分享

各位少年: 我来分享一个输入函数,scanf函数 是输入的函数,scanf(“参数1”,参数2);好,我们接着看代码的例子 int main() { int score0; printf("请输入成绩:"); scanf("%d",&sco…

Android应用-flutter使用Positioned将控件定位到底部中间

文章目录 场景描述示例解释 场景描述 要将Positioned定位到屏幕底部中间的位置,你可以使用MediaQuery来获取屏幕的高度,然后设置Positioned的bottom属性和left或right属性,一般我们left和right都会设置一个值让控制置于合适的位置&#xff0…

【Amazon 实验②】Amazon WAF功能增强之使用Cloudfront、Lambda@Edge阻挡攻击

文章目录 一、方案介绍二、架构图三、部署方案1. 进入Cloud9 编辑器,新打开一个teminal2. 克隆代码3. 解绑上一个实验中Cloudfront 分配绑定的防火墙4. 使用CDK部署方案5. CDK部署完成6. 关联LambdaEdge函数 四、方案效果 一、方案介绍 采用 LambdaEdge DynamoDB 架…

第一部分 数理逻辑

目录 什么是命题 注意: 例1 下列句子中那些是命题? 联结词 例2 将下列命题符号化. 注意: 例4 设 p:天冷,q:小王穿羽绒服,将下列命题符号化 例5 求下列复合命题的真值 例如 真值表: 例&#xff1…

OpenHarmony 4.0 Release发布,同步升级API 10

不久之前,OpenHarmony 正式发布了4.0 版本,开发套件也同步升级到 API 10。相比 3.2 Release 版本,4.0 版本新增 4000 多个 ArkTS API,应用开发能力更加丰富;HDF 新增 200 多个 HDI 接口,硬件适配更加便捷&a…

深度学习数据处理(一)

在PyTorch中,torch.Tensor是存储和变换数据的主要工具。如果你之前用过NumPy,你会发现Tensor和NumPy的多维数组非常类似。然而,Tensor提供GPU计算和自动求梯度等更多功能,这些使Tensor更加适合深度学习。 张量(tensor&…

基于ssm+jsp理发店管理系统源码和论文

随着信息化时代的到来,管理系统都趋向于智能化、系统化,理发店管理系统也不例外,但目前国内的市场仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大,人工管理显然已无法应对时代的变化&#xff0…

【万能技巧】IP知识速通与小技巧~

本文目录 前言一、网络代理IP简介二、IPIDEA 优势2.1 多种类型IP代理2.2 海量纯净代理池2.3 稳定高效数据收集架构 三、IP实操小Tips3.1 查看本地网络IP3.2 使用浏览器IP3.3 使用IPIDEA进行爬虫实操 前言 各位友友,大家好,马上就到2024年了,…

[Angular] 笔记 6:ngStyle

ngStyle 指令: 用于更新 HTML 元素的样式。设置一个或多个样式属性&#xff0c;用以冒号分隔的键值对指定。键是样式名称&#xff0c;带有可选的 .<unit> 后缀&#xff08;如 ‘top.px’、‘font-style.em’&#xff09;&#xff0c;值为待求值的表达式&#xff0c;得到…

【泛型中K T V E? Object等分别代表什么含 义】

✅ 泛型中K T V E? Object等分别代表什么含义 ✅ 典型解析✅代码示例 ✅ 典型解析 E - Element (在集合中使用&#xff0c;因为集合中存放的是元素) T-Type (Java 类) K- Key (键) V - Value (值) N - Number (数值类型) ? - 表示不确定的iava类型 (无限制通配符类型) …