java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot循环调用

SpringBoot解决循环调用问题

作者:Long-龙哥

作者在将SpringBoot从1.5版本升级至2.6版本,并迁移至阿里云上运行后,遇到了循环调用问题,在Jetty容器中运行没问题,但在Tomcat容器中就出现了循环引用问题,原因是SpringBoot 2.6不鼓励循环引用,暴露出该问题,作者提供了两种解决思路

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 的时候报错了。

3. 既然已经知道是循环调用的问题,那么网上搜个logback的配置吧。让它直接打印各个对象的加载和调用log吧

配它!!

<logger name="org.springframework.boot">
	<level value="trace"/>
	<appender-ref ref="stdout"/>
</logger>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文