最近开发遇到一个问题,IDEA服务启动卡住了,找不到具体问题,启动spring boot服务,日志打印到AutowiredAnnotationBeanPostProcessor然后就卡住不动,日志如下:
2020-09-16T15:49:08.315+0800 INFO [main] o.s.b.f.a.AutowiredAnnotationBeanPostProcessor.:155 - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2020-09-16T15:49:08.740+0800 INFO [pool-5-thread-1] m.s.i.schedule.IFTTTScheduleService.refreshProductIFTTT:162 - ProductIFTTT query start
2020-09-16T15:49:08.741+0800 INFO [pool-5-thread-2] m.s.i.schedule.IFTTTScheduleService.refreshOpenProduct:145 - openProducts query start
2020-09-16T15:49:08.741+0800 INFO [pool-5-thread-3] m.s.i.schedule.IFTTTScheduleService.refreshPythonRules:131 - BuiltInScript query start
2020-09-16T15:49:08.741+0800 INFO [pool-5-thread-4] m.s.i.schedule.IFTTTScheduleService.refreshCustomRules:111 - CustomRule query start
2020-09-16T15:49:08.743+0800 INFO [pool-5-thread-2] o.s.c.a.AnnotationConfigApplicationContext.prepareRefresh:583 - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6bb316cf: startup date [Wed Sep 16 15:49:08 CST 2020]; parent: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6fbc1bb
2020-09-16T15:49:08.779+0800 INFO [pool-5-thread-2] o.s.b.f.a.AutowiredAnnotationBeanPostProcessor.:155 - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
通过IDEA的Get Thread Dump功能看到线程在等待:
Get Thread Dump
通过Get Thread Dump查看线程中卡在的方法,发现卡是启动时,线程中的查询方法。
refreshOpenProduct方法
findAllProductIFTTT
DefaultSingletonBeanRegistry.getSingleton
AbstractApplicationEventMulticaster.getApplicationListeners
怀疑是线程的问题,去掉线程,直接调用方法,没问题。确定是加了线程导致的问题。换了一个方法暂时解决。但是需要弄清楚问题的本质,从源头解决。
出现问题的线程池
改写注入方法
怀疑是:可能是因为用线程池导致对象被多次注入。基于此,改写了使用线程池的服务的注入方法,去掉@Autowired,使用构造方法注入。
使用@Autowired注入
使用构造方法注入依赖
重新启动,观察
可以看到,启动报错了,提示服务循环依赖,真相大白!!这代码写得有点乱,把这个依赖的服务查询放到另外的服务中,去掉依赖,重启服务,问题消失,解决!收工!
启动报错
后记
@Autowired注入,服务启动检查不到循环依赖,所以推荐使用更严谨的写法,在构造方法的时候把依赖的服务注入。
关于线程中服务出现循环依赖,导致的服务启动线程卡住,具体原因需要分析spring的启动过程以及 线程池相关知识。
今天的教程就到这里,喜欢的话,欢迎点赞,谢谢!