为什么SpringBoot中Class.forName的类与引入组件(Jar包)用Class.forName得出的class不同

今天发生一个诡异的问题,就是当代码打包进jar包后,调用时发现类找不到。

下面是一段定时器Bean自动创建的启动代码,采用SpringContext拿到接口Bean列表后,进行quartz启动。由于quartz的JobBuilder.newJob需要Class,因此很简单的想到去Class.forName,下面代码在IDE开发环境也是没问题的:

Class<? extends Job> aClass = (Class <? extends Job>)Class.forName(jobClass);

但是打包jar发布后在发布环境却出现了ClassNotFoundException。

问了下GPT,GPT如下回答:

在Spring Boot应用程序中,使用Class.forName()加载类与直接引入组件(Jar包)的方式得到的Class对象可能不同,这通常是由于类加载器的差异引起的。

在Java中,类加载器负责加载类到内存中。Class.forName()方法默认使用的是调用它的类的类加载器。而在Spring Boot中,类加载器的层次结构可能会有所不同,具体取决于应用程序的配置和类路径的设置。

当你直接引入一个组件(Jar包)时,通常会使用默认的类加载器(如应用程序类加载器)来加载该组件中的类。这意味着直接引入的类与通过Class.forName()加载的类可能由不同的类加载器加载,即使它们具有相同的类名和包名,它们也被视为不同的类。

为了解决这个问题,你可以通过提供明确的类加载器来调用Class.forName()方法,例如:

Class.forName("com.example.MyClass", true, Thread.currentThread().getContextClassLoader());

这将确保Class.forName()使用与应用程序中其他组件相同的类加载器加载类,从而避免类加载器的不一致性问题。

于是问题解决,看来spring初始化加载器和主加载器不同。修改为以下代码于是解决:

Class<? extends Job> aClass = (Class <? extends Job>)Class.forName(jobClass, true, Thread.currentThread().getContextClassLoader());

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值