BeanNotOfRequiredTypeException: Bean named 'fundingTransfer' is expected to be of type '***.api.facade.IFundingTransfer' but was actually of type '***.FundingTransfer'

异常情况:本机IDEA启动项目,启动失败异常堆栈信息如下:

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'fundingTransfer' is expected to be of type '***.transfer.api.facade.IFundingTransfer but was actually of type '***.transfer.facade.FundingTransfer'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:378)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:522)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:627)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:318)
... 48 common frames omitted

第一反应:类型不匹配?是不是代码不一致的问题?然后就是拉取最新代码,reimport maven。重启服务,异常依旧。

第二反应:是不是IDEA有缓存?maven重新编译,甚至重启了IDEA。重启服务,异常依旧

代码编译没问题,启动有问题?根据堆栈信息,打断点进行调试。发现在一下代码判断有问题

  if (!ClassUtils.isAssignableValue(requiredType, convertedValue))

理论上来说,convetedValues是实现了requiredType这个接口,

调试打印出convertedValue实现的接口:convertedValue.getClass().getInterfaces(),发现并没有问题。

再次打印出convertedValue的ClassLoader:convertedValue.getClass().getClassLoader(),发现它的类加载器是:RestartClassLoader

打印出requireType的ClassLoader: requiredType.getClassLoader(),发现它的类加载器是:Launcher$AppClassLoader(这个就是我们常说的应用类加载器)

发现它们两个的类加载器并不相同。那么RestartClassLoader是从哪里来的,为什么convertedValue这个对象是被它加载的。

下面这篇文章给了我们答案:RestartClassLoader

By default, any open project in your IDE will be loaded using the “restart” classloader, and any regular .jar file will be loaded using the “base” classloader. If you work on a multi-module project, and not each module is imported into your IDE, you may need to customize things. To do this you can create a META-INF/spring-devtools.properties file.

The spring-devtools.properties file can contain restart.exclude. and restart.include. prefixed properties. The include elements are items that should be pulled up into the “restart” classloader, and the exclude elements are items that should be pushed down into the “base” classloader. The value of the property is a regex pattern that will be applied to the classpath.

针对我们的项目,刚好是,接口定义在依赖包中,依赖包(regular .jar)中有个类("base" ClassLoader)需要注入接口实例,接口实例是在项目中定义并添加到spring容器中的("restart" classloader),导致类型判断有问题。

上面的这篇文章给了我们解决方案:

1、在项目依赖中去掉:spring-boot-devtools这个依赖

2、定义配置文件

原文地址:https://www.cnblogs.com/damon-blogs/p/14927106.html