记一次处理Spring-boot使用dubbo类型转换失败的问题

news/2024/11/25 19:48:59/

第一步、使用父类接收子类,类型转换失败,猜测是不是父子类不能接收,(应该不可能,但还是试下);
第二步、使用同一个类接收,还是类型转换失败;
com.book.common.result.RestResponse 不能转换为com.book.common.result.RestResponse 后面加了
org.springframework.boot.devtools.restart.classloader.RestartClassLoader
第三步、查看报错信息,同一个类型转换失败,但后面加了个RestartClassLoader,没有引入自己实现过这个ClassLoader啊,一般用的是

Bootstrap ClassLoader(引导类加载器):加载JDK核心类库,路径在 JAVA_HOME/lib下面的JAR,自己新加一个JAR放在这个目录下,它也不会加载,它只加载JDK核心类库,包必须是(sun、java、javax开头的类),用C/C++调用,JAVA打印是NULL

Extension ClassLoader(扩展类加载器):开发者可以直接使用扩展类加载器,该加载器负责加载java_home/lib/ext目录下类库;开发者也可以使用扩展类加载器加载-Djava.ext.dir指定目录下的类库。

App ClassLoader(应用类加载器):应用类加载器主要用于加载系统应用的class文件。它负责加载系统类路径java -classpath或-D java.class.path 指定路径下的类库,也就是我们经常用到的classpath路径,开发者可以直接使用系统类加载器,一般情况下该类加载是程序中默认的类加载器,通过getSystemClassLoader()方法可以获取到该类加载器,Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象,而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式即把加载类的动作交由父类处理,是一种任务委派模式,我们代码里面自己写的类,一般用这个加载器。

User ClassLoader(自定义加载器):对某些特殊的类想要进行特殊的加载处理,可以使用自定义ClassLoader,自定义ClassLoader只需要继承抽象类java.lang.ClassLoader,之后重载方法 findClass(String name) 哪些类需要使用当前加载器,可以重载loadClass(String path)怎么加载类。

同一个对象,加载器不同,加载到内存中之后,也不属于一个对象,这里也涉及到了为什么使用双亲委派模式,这里暂时不展开写什么是双亲委派,可以查百度。

第四步、根据上面的代码,可以猜测,应该是使用AppClassLoader,怎么打印了一个RestartClassLoader的加载器,是不是因为ClassLoader不同造成了对象不能转换,之后断点到对象,打印对象 obj.getClass().getClassLoader(),Dubbo返回的对象却是是AppClassLoader,但直接在代码处new一个相同的对象,打印的ClassLoader却是RestartClassLoader,所以转换失败,原因已找到;

解决办法:
1、找到引入RestartClassLoader的地方,发现是spring-boot-devtools,Spring 提供的热部署工具引入的,移除热部署工具,但我用了热部署工具做初始化boot-starp.yml加载,移除之后,这个加载的配置也需要重新处理,很麻烦;
2、指定RestResponse用AppClassLoader加载;
在这里插入图片描述
源码解析:org.springframework.boot.devtools.settings.DevToolsSettings会加载配置
org.springframework.boot.devtools.restart.ChangeableUrls的构造方法会根据配置确定哪些jar和目录需要使用RestClassLoader,把指定的类排除,之后就可以了,但这个只能指定很细粒度的;
3、使用Bootstrap或Extension的ClassLoader做返回,这样也能正常返回,比如用Object接收,但对Dubbo返回的对象,使用强转,也存在加载器不同,不能强转的问题,之后就需要借助反射,反射针对的是属性和方法,不同的加载器也是可以处理的,这样就处理了一个,但每个地方都需要反射,就提炼出一个公共的类处理
在这里插入图片描述
这样也能正常使用,但对存在子对象的也需要特殊除了;

目前使用的是第三种方法,可以根据实际情况调整使用方法,问题暂时解决。


http://www.ppmy.cn/news/101664.html

相关文章

Rust每日一练(Leetday0014) 组合总和II、缺失正数、接雨水

目录 40. 组合总和 II Combination Sum II 🌟🌟 41. 缺失的第一个正数 First Missing Positive 🌟🌟🌟 42. 接雨水 Trapping Rain Water 🌟🌟🌟 🌟 每日一练刷题…

【阿里巴巴国际站API接口】商品详情接口,代码封装系列

为了进行电商平台 alibaba 的API开发,首先我们需要做下面几件事情。 1)开发者注册一个账号 2)然后为每个alibaba应用注册一个应用程序键(App Key) 。 3)下载 alibaba API的SDK并掌握基本的API基础知识和调用 4&#xf…

用最少的代码模拟gRPC四种消息交换模式

我们知道,建立在HTTP2/3之上的gRPC具有四种基本的通信模式或者消息交换模式(MEP: Message Exchange Pattern),即Unary、Server Stream、Client Stream和Bidirectional Stream。本篇文章通过4个简单的实例演示它们在.NE…

Linux使用PowerShell模块管理MsSql-Server

1.安装PowserShell 更新包列表 sudo apt-get update 安装依赖: sudo apt-get install -y wget apt-transport-https software-properties-common 下载 key: wget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb&…

MySQL — 视图、存储过程、触发器

文章目录 视图/存储过程/存储函数/触发器一、视图1.1 语法1.1.1 创建视图1.1.2 查询1.1.3 修改1.1.4 删除1.1.5 对数据的操作 1.2 检查选项1.2.1 cascaded1.2.2 local 1.3 视图的更新1.4 视图的作用1.5 案例1.5.1 案例11.5.2 案例2 二、存储过程2.1 介绍2.2 基本语法2.3 变量2.…

项目复盘四步:怎么做才有成效?这些关键点不可忽略

在项目管理中,及时复盘是非常重要的,因为只有通过反思和分析,才能找到差距存在的原因。 复盘分析的第一步是回顾目标 因为目标是工作开展的关键。在执行项目的过程中,要始终朝着所设定的目标去努力实现。计划和现实会存在偏差&…

Linux-0.11 入口函数main.c详解

Linux-0.11 入口函数main.c详解 模块简介 main.c大部分代码主要是对内核进行初始化,而main.c开始,就都是c语言编写的内核了。 函数详解 time_init static void time_init(void)该函数读取CMOS时钟信息作为系统的开机时间。 struct tm time;do {time…

选择交换机主要看哪些参数指标

交换机有几个性能指标您一定要知道哦,和海翎光电的小编一起温故而知新。 网络构成方式:接入层交换机、汇聚层交换机、核心层交换机 OST模型:第二层交换机、第三层交换机、第四层交换机……第七层交换机 交换机的可管理性:可管理…