工作思考|研发环境好好的,怎么上线就出问题了?

场景再现

那是一个夜黑风高的晚上,某个版本迭代经过了完备的测试,正准备上线。研发同事A开完了上线评审后,信心满满地对运维同事B说:"开冲!"

几分钟后,同事B发了条消息过来,看着抖动的头像,同事A心想:小B效率真高啊,这么快!点开消息一看【启动报错了,你看一下】。

什么?启动还能报错,不可能啊,我研测环境都好好的。

小A火急火忙地连上堡垒机,看了下日志,报错信息大致为 【表tb_xxx没有找到】。

"怎么可能,我用了伟大的flyway,怎么可能会没有表呢?"小A如是说道。

提到flyway,这里简单介绍一下。Flyway是一款开源的数据库版本管理工具,可以实现管理并跟踪数据库变更,支持数据库版本自动升级,而且不需要复杂的配置,能够帮助团队更加方便、合理的管理数据库变更。只需要引入相应依赖,添加配置,再在resource目录下创建db/migration/xxxx.sql文件,在sql文件中写入用到的建表语句,插入语句即可。

不管怎么说,代码是不会骗人的。先找下是哪里出了问题!

小A很快就定位到了代码位置,是一个用于缓存的HashMap,这操作也没什么问题,相信大家都这么用过,对于一些一次查找,到处使用,还亘古不变的表信息,可以先查一次,把它用Map缓存起来,以便后续使用。

但是研发同事C把这段代码放在了afterPropertiesSet()​方法内部,没错,就是那个InitializingBean​接口的方法。看到这里,相信各位熟练背诵Bean生命周期的Java Boy已经明白了!查询数据库的操作在Bean还没有创建完成的时候就进行了!而此时,flyway脚本还没有执行,自然就找不到对应的表信息了。

那怎么办呢?

解决方法

解决方法很简单,sql执行的时候找不到表,那就让它在表创建完之后再执行!

1.CommandLineRunner接口

一个方法就是我们常用的CommandLineRunner​接口,重写run()​方法,把缓存逻辑移到run()​方法中。原因是run()方法的执行时机是在SpringBoot应用程序启动之后,此时flyway已经执行完毕,表结构已经存在,就没问题了!

2.@DependsOn注解

通过代码分析,flyway的加载是由flywayInitializer​这个Bean负责的。所以只需要我们的Bean在它之后加载就行了,这就用上了@DependsOn​注解。

@DependsOn注解可以定义在类和方法上,意思是我这个Bean要依赖于另一个Bean,也就是说被依赖的组件会比该组件先加载注册到IOC容器中。

也就是在我们的Bean上加上这么个注解@DependsOn("flywayInitializer")

总结

此次线上问题复习了Bean的生命周期,复习了InitializingBeanCommandLineRunner​两个接口,复习了@DependsOn​注解。

相关推荐
zwhdlb6 分钟前
Java + 工业物联网 / 智慧楼宇 面试问答模板
java·物联网·面试
刘一说22 分钟前
CentOS 系统 Java 开发测试环境搭建手册
java·linux·运维·服务器·centos
卷福同学29 分钟前
来上海三个月,我在马路边上遇到了阿里前同事...
java·后端
bingbingyihao2 小时前
多数据源 Demo
java·springboot
在努力的前端小白7 小时前
Spring Boot 敏感词过滤组件实现:基于DFA算法的高效敏感词检测与替换
java·数据库·spring boot·文本处理·敏感词过滤·dfa算法·组件开发
一叶飘零_sweeeet10 小时前
从繁琐到优雅:Java Lambda 表达式全解析与实战指南
java·lambda·java8
艾伦~耶格尔10 小时前
【集合框架LinkedList底层添加元素机制】
java·开发语言·学习·面试
一只叫煤球的猫10 小时前
🕰 一个案例带你彻底搞懂延迟双删
java·后端·面试
最初的↘那颗心10 小时前
Flink Stream API 源码走读 - print()
java·大数据·hadoop·flink·实时计算
JH307311 小时前
Maven的三种项目打包方式——pom,jar,war的区别
java·maven·jar