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

场景再现

那是一个夜黑风高的晚上,某个版本迭代经过了完备的测试,正准备上线。研发同事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​注解。

相关推荐
秋千码途8 分钟前
小架构step系列08:logback.xml的配置
xml·java·logback
飞翔的佩奇10 分钟前
Java项目:基于SSM框架实现的旅游协会管理系统【ssm+B/S架构+源码+数据库+毕业论文】
java·数据库·mysql·毕业设计·ssm·旅游·jsp
时来天地皆同力.29 分钟前
Java面试基础:概念
java·开发语言·jvm
找不到、了1 小时前
Spring的Bean原型模式下的使用
java·spring·原型模式
阿华的代码王国1 小时前
【Android】搭配安卓环境及设备连接
android·java
YuTaoShao1 小时前
【LeetCode 热题 100】141. 环形链表——快慢指针
java·算法·leetcode·链表
铲子Zzz2 小时前
Java使用接口AES进行加密+微信小程序接收解密
java·开发语言·微信小程序
霖檬ing2 小时前
K8s——配置管理(1)
java·贪心算法·kubernetes
Vic101013 小时前
Java 开发笔记:多线程查询逻辑的抽象与优化
java·服务器·笔记
Biaobiaone3 小时前
Java中的生产消费模型解析
java·开发语言