前阵子接手了一段同事之前的代码,里面用到了@transaction注解,了解Spring的小伙伴肯定知道,@Transactional是Spring提供的一种控制事务管理的快捷手段。但是我这段程序在运行的时候,经常出现莫名其妙的问题,连夜研究了好久才搞清楚,在这里记录一下, 避免大家入坑。
1. 大家来找茬
在介绍具体问题之前,我把问题代码简化了一下,看大家能找到其中的问题吗?
问题代码1
下面的这段代码主要是想利用MySQL里面的行锁select for update
,来实现简单的分布式锁。但是在实践过程中,发现这个锁好像并没有生效,而且在数据库的里面也没有查找对应transaction连接的信息。
@Component
@EnableScheduling
public class someService {
@Scheduled(...)
public doSomeWork() {
// find some id by logic
// process the related info
doOtherWork(id);
}
@Transactional(isolation = Isolation.READ_COMMITTED)
public void doOtherWork(id) {
Info info = requestMapper.selectByPrimaryKeyForUpdate(id);
doSomeFollowingProcess(info);
...
}
}
问题代码2
下面代码分两个步骤,第一步会检查相关信息,第二步调用了一个transactional修饰的方法,完成一些基本工作;但在实践中,发现一个非常诡异的问题,在MainWork中,doSomeCheck执行时会抛出nullPointException,debug发现所有autowired进来的service均为空,注释掉doSomeCheck里面的内容后,继续往下执行,却发现doWork能够正常执行,所有的注入均没有问题。
@Component
public class MainWork {
@AutoWired
DetailWork detailWork
public void workflow() {
detailWork.doSomeCheck();
detailWork.doWork();
}
}
@Component
public class DetailWork {
@AutoWired
UsefulService usefulService;
@AutoWired
InfoService infoService;
@Transactional(isolation = Isolation.READ_COMMITTED)
public void doWork() {
usefulService.doSomeWork();
}
void doSomeCheck() {
infoService.getInfo();
}
}
大伙看看能发现什么问题吗?