> 技术文档 > Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String 的解决办法_invalid value type for attribute \'factorybeanobjec

Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String 的解决办法_invalid value type for attribute \'factorybeanobjec


问题概述

关于这个问题,博主是在跑单元测试的时候遇到的,本篇文章可能较长,如果只想解决问题本身,可只关注结果,跳过过程!

环境:

spring-boot 3.2.1
jdk 17

报错:“ Caused by: java.lang.IllegalArgumentException: Invalid value type for attribute \'factoryBeanObjectType\': java.lang.String

莫名的参数类型错误,

如下图

具体信息如下:

java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@4b74b35 testClass = ...ApplicationTests, locations = [], classes = [com...Application], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = [\"org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true\"], contextCustomizers = [org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7bd4937b, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@741a8937, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@2ea41516, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@4b0d79fc, org.springframework.boot.test.context.SpringBootTestAnnotation@4a86e4f0], resourceBasePath = \"src/main/webapp\", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:180)at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130)at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191)at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130)at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163)at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)at java.base/java.util.Optional.orElseGet(Optional.java:364)at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)Caused by: java.lang.IllegalArgumentException: Invalid value type for attribute \'factoryBeanObjectType\': java.lang.Stringat org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes(FactoryBeanRegistrySupport.java:86)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:836)at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:620)at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:575)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:534)at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:138)at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:789)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:606)at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762)at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:464)at org.springframework.boot.SpringApplication.run(SpringApplication.java:334)at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1458)at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:552)at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225)at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152)... 17 moreProcess finished with exit code -1

解决办法

根据错误信息,参数类型错误

参考【mybatis-spring-issues 855】得知:

在 Spring Boot 3.0后的 版本中FactoryBeanRegistrySupport#getTypeForFactoryBeanFromAttributes方法已变更,如果 factoryBeanObjectType 不是 ResolvableType 或 Class 类型会抛出 IllegalArgumentException 异常。

此时因为 factoryBeanObjectType 是 String 类型,不符合条件而抛出异常。

如下图:

项目中使用的 mybatis-plus-boot-starter 是当前最新版本 3.5.5,但 mybatis-spring 为2.1.2 

如下图:

但版本已不兼容,

兼容对照表:

MyBatis-Spring-Boot-Starter、MyBatis-Spring、Spring Boot、Java 版本兼容对照如下表:

好了,问题分析清楚了,

可以解决问题了,

第一步:排除 mybatis-plus-boot-starter 中的旧版本 mybatis-spring

  com.baomidou mybatis-plus-boot-starter 3.5.5    mybatis-spring  org.mybatis   

第二步:引入 mybatis-spring 3.0.3 版本

  org.mybatis mybatis-spring 3.0.3 

完整内容:

   com.baomidou mybatis-plus-boot-starter 3.5.5    mybatis-spring  org.mybatis     org.mybatis mybatis-spring 3.0.3 

第三步:测试

再次跑单元测试,就成功执行了,如下图:

源码扩展,可忽略:

Springboot Version 3.2.0-M2,spring-boot-starter 3.0.2 在这个版本中,FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes()方法已经改变,当“factoryBeanObjectType”不是ResolvableType或者Class类型时抛出一个IllegalArgumentException,

如下图:

org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getTypeForFactoryBeanFromAttributes

通过检查FactoryBean的属性来确定FactoryBean的bean类型
从ResolvableType中提取属性或者ResolvableType.NONE,
很遗憾,从ResolvableType中未找到FactoryBean的属性或者ResolvableType.NONE,

但是在 org.mybatis.spring.mapper.ClassPathMapperScanner.processBeanDefinitions()方法(第254行)设置一了个字符串类型beanClassName,

如下图:

在 mybatis-spring-3.0.3 通过反射创建一个Class类:

 String beanClassName = definition.getBeanClassName(); LOGGER.debug(() -> \"Creating MapperFactoryBean with name \'\" + holder.getBeanName() + \"\' and \'\" + beanClassName + \"\' mapperInterface\"); // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59 try { Class beanClass = Resources.classForName(beanClassName); // Attribute for MockitoPostProcessor // https://github.com/mybatis/spring-boot-starter/issues/475 definition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, beanClass); // for spring-native definition.getPropertyValues().add(\"mapperInterface\", beanClass); } catch (ClassNotFoundException ignore) { // ignore }

如下图:

 到这里,就可以成功识别到Class类型了:

自此,问题就解决了,项目的单元测试模块跑通了,如下图:

其它补充:


好了,关于 Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String 的解决办法  就写到这儿了,如果还有什么疑问或遇到什么问题欢迎扫码提问,也可以给我留言哦,我会一一详细的解答的。 
歇后语:“ 共同学习,共同进步 ”,也希望大家多多关注CSND的IT社区。


作       者: 华    仔 联系作者: who.seek.me@java98k.vip 来        源: CSDN (Chinese Software Developer Network) 原        文: https://blog.csdn.net/Hello_World_QWP/article/details/135771075 版权声明: 本文为博主原创文章,请在转载时务必注明博文出处!