SpringBoot解决循环调用问题
作者:Long-龙哥
SpringBoot解决循环调用
此文仅记录自身遇到的问题进行解决处理思路。
背景
项目为springboot-1.5的版本,迁移上阿里云,提升springboot版本为2.6.当初最开始的时候用的是jetty容器在本地进行启动,但是最后需要将工程迁移到ali cloud,并且运用K8S作为容器,所以最后将项目打包方式改为jar包。
Jetty 运行的时候是没有丝毫的问题,但是用自带的tomcat 的时候问题就暴漏出来了。
原因应该是循环引用对于springboot2.6来说是不被鼓励的,所以会直接暴漏出来,最直接简单粗暴的方法:
第一种解决思路
下面为允许循环调用的配置操作:
spring.main.allow-circular-references=true
第二种解决思路
因为用最简单的方式进行循环调用,表象一是自己故意做出来的,表象2为当时遇到的。故将两种表象都进行记录,
所谓循环调用无非就是A调用B,B调用A,导致的springboot 在进行对象加载的时候的一种冲突。下面具体介绍解决思路。
表象1:
此为最简单,也是最容易发现的一种循环调用表现:
2022-10-02 08:44:55.456 WARN 17112 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'a': Unsatisfied dependency expressed through field 'b'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'b': Unsatisfied dependency expressed through field 'a'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?
2022-10-02 08:44:55.456 INFO 17112 --- [ main] ConditionEvaluationReportLoggingListener :Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-10-02 08:44:55.472 ERROR 17112 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :***************************
APPLICATION FAILED TO START
***************************Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| a (field private com.example.service.B com.example.service.A.b)
↑ ↓
| b (field private com.example.service.A com.example.service.B.a)
└─────┘
表象2:
此种直接导致tomcat启动失败,并且在关闭tomcat的时候直接失败,且出现了内存泄漏的问题,错误是一样的,顺手从网上粘贴了一个
07-Sep-2020 19:09:11.196 WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [system] appears to have started a thread named [pool-1-thread-4] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
java.lang.Thread.run(Thread.java:748)
- 表象一直接是在控制台看到的,没啥好说的
- 表象二这种应用启动的时候直接就提示会造成内存泄漏,但是具体的错误信息是没有的。
当时解决的时候是分为了一下几步:
1.main方法进行debug模式。调节logbcak日志级别为debug,但是效果不是很明显。依然看不到具体的错误信息。
2.然后自己就只能盲猜了,直接上断点给各种config注解,datasource,很幸运,当加载datasource 的时候报错了。
- 然后放开断点,没问题出现了表象2的问题,原因是我们使用的druid连接池里面的filter配置,最后注释掉,加载成功了,但是问题依然存在。
- 那就干脆直接从断点出入手,一路加载debug下去,最后发现了create bean 的时候出现了问题,此时便发现了循环调用的问题。
- OK,处理掉之后,本地已经可以正常run 起来了。然而,在上到服务器的时候依旧报表象2的错误。
3. 既然已经知道是循环调用的问题,那么网上搜个logback的配置吧。让它直接打印各个对象的加载和调用log吧
配它!!
<logger name="org.springframework.boot"> <level value="trace"/> <appender-ref ref="stdout"/> </logger>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。