Spring:InvalidDefinitionException: Direct self-reference leading to cycle

news2025/1/11 4:57:04

一、现象

一个列表接口报错,没有返回信息,异常堆栈如下:

11:52:05.096 [http-nio-8180-exec-36] ERROR c.u.s.f.w.e.GlobalExceptionHandler - [handleRuntimeException,65] - 请求地址'XXXXX',发生未知异常.
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class XXXX]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: XXXX.page.TableDataInfo["rows"]->java.util.ArrayList[0]->XXXX["instance"])
        at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:462)
        at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104)
       ....
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: XXXX.page.TableDataInfo["rows"]->java.util.ArrayList[0]->XXXX["instance"])
        at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
        at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1276)
        at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._handleSelfReference(BeanPropertyWriter.java:944)
        at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:722)
        at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
        at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
        at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
        at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
        at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
        at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
        at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
        at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
        at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1514)
        at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1006)
        at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:456)
        ... 121 common frames omitted

二、解决办法

  1. 不要在可能序列化的Bean内写这种奇怪的方法(这是同事写的方法,至于他写这个方法的原因我下面讲)
	public XXXX getInstance(){
        return this;
    }

或者

	public XXXX getInstance(){
        return new XXXX();
    }
  1. 如果调用的地方不多可以修改方法名,不以get或is开头
  2. 在不需要(不能)序列化的getXXX方法上加@JsonIgnore注解
  3. 好好学习:-(

三、原因分析

spring在使用默认的Jackson对接口返回的数据序列化时出现了直接引用自循环的现象,遂抛出异常。
自循环出现的地方如下:
在这里插入图片描述
看了一下调用这个方法的地方只有一处:

在这里插入图片描述

那么写这个getInstance的原因也就清楚了,为了在toMap的时候将自身作为value。
至此我诚心得为您推荐:

Function.identity()

他的内容很简单:

    /**
     * Returns a function that always returns its input argument.
     *
     * @param <T> the type of the input and output objects to the function
     * @return a function that always returns its input argument
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }

扩展

我们看一下jackson是如何将 getInstance方法当做一个需要序列化的属性的。

1.启动时加载默认配置,认定’get’、‘set’、'is’开头的方法可能需要被序列化

在springboot启动时会使用

DefaultAccessorNamingStrategy$Provider

这个默认配置,设定以’get’、‘set’、'is’为开头的方法可能需要被序列化
在这里插入图片描述
启动进行默认配置时的堆栈:

<init>:286, DefaultAccessorNamingStrategy$Provider (com.fasterxml.jackson.databind.introspect)
<clinit>:370, ObjectMapper (com.fasterxml.jackson.databind)
build:672, Jackson2ObjectMapperBuilder (org.springframework.http.converter.json)
<init>:59, MappingJackson2HttpMessageConverter (org.springframework.http.converter.json)
<init>:91, AllEncompassingFormHttpMessageConverter (org.springframework.http.converter.support)
<init>:215, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
instantiateClass:211, BeanUtils (org.springframework.beans)
instantiate:87, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
instantiateBean:1326, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1232, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:582, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:542, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:335, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 60187547 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$49)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:333, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:208, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:953, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:918, AbstractApplicationContext (org.springframework.context.support)
refresh:583, AbstractApplicationContext (org.springframework.context.support)
<init>:144, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:85, ClassPathXmlApplicationContext (org.springframework.context.support)
main:32, XXXApplication (com.XXX)

2.controller处理完请求后为返回的POJO查找需要序列化的属性

请求在DispatcherServlet doDispatch中交给controller进行处理,controller处理完后的返回结果经过RequestResponseBodyMethodProcessor的handleReturnValue方法:
在这里插入图片描述
后在AbstractJackson2HttpMessageConverter的writeInternal方法中交给默认的Jackson:ObjectWriter完成POJO的序列化
在这里插入图片描述
继续跟踪,能看到Jackson在实例化前的准备工作,看一下这个方法:POJOPropertiesCollector.getJsonValueAccessor()
在这里插入图片描述
_collected属性被用来控制对一个POJO的解析只进行一次。(这种工作当然只需要做一次就够了)
而在collectAll方法的最后则会缓存解析的结果,并关闭收集开关。
在这里插入图片描述
到这里我们已经离这一小节的目标很近了。看一下collectAll方法里的细节:
在这里插入图片描述
_addFields(props)和_addMethods(props)方法将类中符合序列化条件的属性和方法加入到结果中,随后再进行筛选转换。
在这两个方法中能看到经常用来忽略序列化的实现逻辑(transient关键字和@JsonIgnore注解)
在这里插入图片描述
_addMethods里通过方法参数个数大致将方法分为getter方法(0参数),setter方法(1参数),anySetter(2参数)
这里我们主要关注getter逻辑中调用的_addGetterMethod,它的前半部分主要是对方法进行初步筛选和注解处理
在这里插入图片描述
后半部分则是试图从方法中获取隐藏的属性名,也就是序列化后的key
在这里插入图片描述
其中,_accessorNaming.findNameForRegularGetter(m, m.getName())方法会将我们定义的getInstance方法作为属性进行切割,将instance作为其属性名加入到prop中
在这里插入图片描述

其中_getterPrefix就是第一小节中初始化的默认配置:“get”
解析属性的堆栈:

_addGetterMethod:782, POJOPropertiesCollector (com.fasterxml.jackson.databind.introspect)
_addMethods:687, POJOPropertiesCollector (com.fasterxml.jackson.databind.introspect)
collectAll:422, POJOPropertiesCollector (com.fasterxml.jackson.databind.introspect)
getJsonValueAccessor:270, POJOPropertiesCollector (com.fasterxml.jackson.databind.introspect)
findJsonValueAccessor:258, BasicBeanDescription (com.fasterxml.jackson.databind.introspect)
findSerializerByAnnotations:391, BasicSerializerFactory (com.fasterxml.jackson.databind.ser)
_createSerializer2:220, BeanSerializerFactory (com.fasterxml.jackson.databind.ser)
createSerializer:169, BeanSerializerFactory (com.fasterxml.jackson.databind.ser)
_createUntypedSerializer:1473, SerializerProvider (com.fasterxml.jackson.databind)
_createAndCacheUntypedSerializer:1421, SerializerProvider (com.fasterxml.jackson.databind)
findContentValueSerializer:753, SerializerProvider (com.fasterxml.jackson.databind)
findAndAddSecondarySerializer:90, PropertySerializerMap (com.fasterxml.jackson.databind.ser.impl)
_findAndAddDynamic:311, AsArraySerializerBase (com.fasterxml.jackson.databind.ser.std)
serializeContents:115, IndexedListSerializer (com.fasterxml.jackson.databind.ser.impl)
serialize:79, IndexedListSerializer (com.fasterxml.jackson.databind.ser.impl)
serialize:18, IndexedListSerializer (com.fasterxml.jackson.databind.ser.impl)
serializeFields:808, MapSerializer (com.fasterxml.jackson.databind.ser.std)
serializeWithoutTypeInfo:764, MapSerializer (com.fasterxml.jackson.databind.ser.std)
serialize:720, MapSerializer (com.fasterxml.jackson.databind.ser.std)
serialize:35, MapSerializer (com.fasterxml.jackson.databind.ser.std)
_serialize:480, DefaultSerializerProvider (com.fasterxml.jackson.databind.ser)
serializeValue:400, DefaultSerializerProvider (com.fasterxml.jackson.databind.ser)
serialize:1510, ObjectWriter$Prefetch (com.fasterxml.jackson.databind)
writeValue:1006, ObjectWriter (com.fasterxml.jackson.databind)
writeInternal:456, AbstractJackson2HttpMessageConverter (org.springframework.http.converter.json)
write:104, AbstractGenericHttpMessageConverter (org.springframework.http.converter)
writeWithMessageConverters:290, AbstractMessageConverterMethodProcessor (org.springframework.web.servlet.mvc.method.annotation)
handleReturnValue:183, RequestResponseBodyMethodProcessor (org.springframework.web.servlet.mvc.method.annotation)
handleReturnValue:78, HandlerMethodReturnValueHandlerComposite (org.springframework.web.method.support)
invokeAndHandle:135, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:895, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:808, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:1067, DispatcherServlet (org.springframework.web.servlet)
doService:963, DispatcherServlet (org.springframework.web.servlet)
processRequest:1006, FrameworkServlet (org.springframework.web.servlet)
doGet:898, FrameworkServlet (org.springframework.web.servlet)
service:645, HttpServlet (javax.servlet.http)
service:883, FrameworkServlet (org.springframework.web.servlet)
service:750, HttpServlet (javax.servlet.http)
internalDoFilter:227, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
。。。。。。。。。
doFilter:117, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:189, ApplicationFilterChain (org.apache.catalina.core)
doFilter:162, ApplicationFilterChain (org.apache.catalina.core)
invoke:197, StandardWrapperValve (org.apache.catalina.core)
invoke:97, StandardContextValve (org.apache.catalina.core)
invoke:541, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:135, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:78, StandardEngineValve (org.apache.catalina.core)
invoke:687, AbstractAccessLogValve (org.apache.catalina.valves)
service:360, CoyoteAdapter (org.apache.catalina.connector)
service:399, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:890, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1743, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1191, ThreadPoolExecutor (org.apache.tomcat.util.threads)
run:659, ThreadPoolExecutor$Worker (org.apache.tomcat.util.threads)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)

ps:偶然发现swagger在项目启动的时候也会使用POJOPropertiesCollector.collectAll方法获取类属性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/644276.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(el-Tree)操作:Element-plus 中Tree 树形控件的样式等的使用

Ⅰ、Element-plus 提供的Tree树形控件组件与想要目标情况的对比&#xff1a; 1、Element-plus 提供Tree组件情况&#xff1a; 其一、Element-ui 自提供的Table代码情况为(示例的代码)&#xff1a; // Element-plus 自提供的代码&#xff1a; // 此时是使用了 ts 语言环境&…

06-揭开神秘面纱:Golang method的魅力解析

&#x1f4c3;个人主页&#xff1a;个人主页 &#x1f525;系列专栏&#xff1a;Golang基础 &#x1f4ac;Go&#xff08;又称Golang&#xff09;是由Google开发的开源编程语言。它结合了静态类型的安全性和动态语言的灵活性&#xff0c;拥有高效的并发编程能力和简洁的语法。G…

宝鸡陇县中学弱电系统集成设计方案_kaic

摘 要 随着世界各国教育信息化的推进&#xff0c;我国在教育信息基础设施和资源上也在逐步加快步伐。校园信息化平台的建设关系到校园网站的技术实现、广播系统、视频监控系统的建设&#xff0c;能够使知识获取更便捷、校园文化生活更丰富、校园管理更精准。利用信息交互的特性…

chatgpt赋能python:Python如何排列输出列表的数

Python如何排列输出列表的数 Python是一门广泛应用于数据分析、科学计算等领域的编程语言&#xff0c;其简洁易学、强大的编程特性使得其成为很多领域中的首选语言。在Python中&#xff0c;列表是一种非常常见的数据结构&#xff0c;其可以存储大量相关数据&#xff0c;并且通…

【八大排序(五)】快排进阶篇-挖坑法+前后指针法

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:八大排序专栏⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习排序知识   &#x1f51d;&#x1f51d; 快排进阶篇 1. 前情回顾2. 思路回顾3. 单…

chatgpt赋能python:Python排列组合:让编程更简单

Python排列组合&#xff1a;让编程更简单 Python是一种现代化的编程语言&#xff0c;同时也是一种强大的工具。在Python中&#xff0c;排列组合是极其重要的一种操作。在本篇文章中&#xff0c;我们将介绍Python中的排列组合&#xff0c;并探讨如何利用Python编程语言进行排列…

十.多线程

1、进程与线程 &#xff08;1&#xff09;操作系统与进程 1.程序&#xff1a;代码。 2.进程&#xff1a;程序的动态执行过程。 &#xff08;2&#xff09;进程与线程 线程&#xff1a;线程&#xff1a;是比进程更小的执行单位&#xff0c;一个进程在其执行过程中&#xff0…

chatgpt赋能python:Python中如何找到编程中的错误

Python中如何找到编程中的错误 Python是一种旨在提高开发者生产力的高级编程语言。由于其简洁性和可读性&#xff0c;它越来越成为开发者们的首选语言。然而&#xff0c;就像其他编程语言一样&#xff0c;Python编程中难免会有错误。本文将介绍一些有用的技巧和工具&#xff0…

STM32速成笔记—概述

文章目录 前言一、专栏简介二、前期准备三、编程规范以及程序架构简介1. 编程规范2. 程序架构 四、STM32F103ZET6简介 前言 本人技术菜鸟一枚&#xff0c;2022年大学毕业&#xff0c;大学加入老师实验室&#xff0c;参加过一些嵌入式相关的比赛&#xff0c;获得过2020年TI杯大学…

【利用AI让知识体系化】简要了解网络七层协议

文章目录 一、前言引言目的和意义 二、网络七层协议简介OSI参考模型七层协议分层结构和各层协议简介 三、物理层 - Layer 1物理层概述物理层的作用物理层标准和协议 四、数据链路层 - Layer 2数据链路层概述常见的协议 五、网络层 - Layer 3网络层概述网络层的作用IP地址的作用…

Nuxt.js:用 Vue.js 打造服务端渲染应用程序

文章目录 I. 简介Nuxt.js是什么Nuxt.js的历史和发展Nuxt.js的特点和优势1. 服务端渲染2. 自动生成路由3. 静态文件服务4. 异步数据加载5. 基于Webpack的构建系统6. 支持模块化的Vue组件7. 可定制的ESLint与StyleLint8. 支持PWA等高级功能 II. Nuxt.js基础Nuxt.js的安装和配置Nu…

ACL2023 | WebCPM:清华发布中文LFQA 数据集,探索搜索引擎和PLM大模型结合新范式

一、概述 title&#xff1a;WEBCPM: Interactive Web Search for Chinese Long-form Question Answering 论文地址&#xff1a;https://arxiv.org/abs/2305.06849 代码&#xff1a;https://github.com/thunlp/WebCPM 1.1 Motivation 开发一个类似于WebGPT一样的中文版本的…

如何保证数据库分布式事务的强一致性

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 针对分布式数据库&#xff0c;如何保证分布式事务的强一致性&#xff0c;是分布式数据库的关键。分布式事务的强一致性方案这里介绍两种&#xff0c;一种是GTM(global transaction manager),另一种是基于XA协议的两阶…

12道前端知识题目深入浅出下JavaScript

文章目录 1. 原型和原型链2. 作用域和闭包3. 高阶函数和函数式编程4. 异步编程和Promise、async/await5. 正则表达式6. 对象属性描述符和代理7. ES6新特性如模板字符串、解构赋值、箭头函数、let/const等8. 设计模式和架构模式设计模式架构模式 9. 性能优化技巧和调试技巧1. 性…

chatgpt赋能python:Python如何持续保存CSV文件

Python如何持续保存CSV文件 如果你需要不断更新数据并将其保存到CSV文件中&#xff0c;Python语言可以轻松完成这个任务。本文将介绍如何使用Python在代码执行的同时&#xff0c;将数据不断写入CSV文件中&#xff0c;实现持续保存的功能。 CSV文件是什么&#xff1f; CSV代表…

chatgpt赋能python:抓包是什么?

抓包是什么&#xff1f; 当我们在浏览器中访问一个网站时&#xff0c;我们的电脑会向网络服务器发送请求并接收响应。这个过程中&#xff0c;有一些工具可以让我们查看和分析这些请求和响应&#xff0c;其中最常用的就是“抓包”。 抓包就是指截获网络通信过程中的数据包并分…

chatgpt赋能python:Python怎么指定循环次数?

Python怎么指定循环次数&#xff1f; Python是一种广泛应用于编程领域的高级编程语言&#xff0c;它具有简单易学、代码可读性强、语言编写规范等诸多优点。其中&#xff0c;循环是Python语法中的重要一环&#xff0c;而如何指定循环次数则是其中一个重要的问题。 什么是循环…

Linux 检测通信路径上的PMTU(路径最大传输单元)

问题描述 终端设备向云端POST数据&#xff0c;数据量较小的没有问题&#xff0c;数据量大的必然出现丢包。网络很通畅&#xff0c;延迟较低。 分析 后来发现&#xff0c;终端到云端的通信路径上某个路由器节点的MTU小于终端的MTU&#xff0c;当终端发出的IP数据包长度大于该…

力扣题库刷题笔记4--寻找两个正序数组的中位数

1、题目如下&#xff1a; 2、个人Python代码实现如下&#xff1a; 代码如下&#xff1a; class Solution: def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float: nums nums1 nums2 #合并数组 nums.sort() …

java【toString覆写】

笔试题 输出结果&#xff1a;D.func(),num0 解析&#xff1a; 继承的原则&#xff0c;先调用父类的无参构造&#xff0c;因此调用func()函数func() 此方法&#xff0c;new 的是 D 的对象&#xff0c;且被D所重写&#xff0c;触发动态绑定&#xff0c;直接调用D中的func()方法在…