No qualifying bean of type ‘java.lang.String‘ available: expected at least 1 bean which qualifies
一、问题复现和详细异常
今天一个同事在开发时给一个类(AServiceImpl
)加了@AllArgsConstructor
,希望通过private final 的方式将XxClass
和 XxxClass
注入到当前类:
@Service
@AllArgsConstructor
public class AServiceImpl implements AService{private final XxClass xxClass;private final XxxClass xxxClass;@Value("${my.value:myValue}")private String value;.....
}
运行时报错如下:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1777) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1333) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1287) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1206) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:571) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.2.jar:5.3.2]at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:923) ~[spring-context-5.3.2.jar:5.3.2]at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588) ~[spring-context-5.3.2.jar:5.3.2]at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.1.jar:2.4.1]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) [spring-boot-2.4.1.jar:2.4.1]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.4.1.jar:2.4.1]at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) [spring-boot-2.4.1.jar:2.4.1]at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) [spring-boot-2.4.1.jar:2.4.1]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) [spring-boot-2.4.1.jar:2.4.1]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) [spring-boot-2.4.1.jar:2.4.1]at com.saint.DemoTestApplication.main(DemoTestApplication.java:10) [classes/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1777)at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1333)at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1287)at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)... 28 common frames omitted
二、原因分析
从报错提示可以看出是没有找到NoSuchBeanDefinition;根本原因是因为springioc容器加载bean默认使用无参构造进行初始化,就示例而言,需要用到只有一个入参的构造函数(AClassImpl(XsClass)
);
由于此处使用的是@AllArgsConstructor
注解,所以对AClassImpl
而言,只有一个构造函数(AClassImpl(XxClass, XxxClass, String)
),而构造函数的第三个参数是用@Value注入导入的一个属性值,其并不会存在于Spring容器,所以报错。
源码分析
从报错信息找到出错的入口:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
这里可以看到获取到的AServiceImpl
的构造函数中有三个入参,最后一个入参是String类型;
然后顺着报错日志的执行链路,找到
这里ConstructorResolver#resolveAutowiredArgument()
方法会判断 用于解析指定参数的模板方法 是否支持被自动注入(autowired);非Class类型均不行。
抛出异常的源码位置如下:
因为采用构造函数注入属性的方式,属性是必须要存在于Spring容器的,所以这里检查参数必须性时会校验不通过(即不会提前return),进而报错;
三、解决方案
一般可以给AServiceImpl提供一个默认的构造方法来解决,但此处需要注入XxClass
和 XxxClass
,所以仅需生成一个只包含XxClass
和 XxxClass
两个参数的构造方法即可。
因此,我们选择使用@RequiredArgsConstructor
注解来替换@AllArgsConstructor
注解;
@RequiredArgsConstructor 和 @AllArgsConstructor的区别?
- @RequiredArgsConstructor会将类的每一个final字段或者non-null字段生成一个构造方法
- @AllArgsConstructor 生成一个包含所有字段的构造方法;
- @NoArgsConstructor 生成无参的构造方法;
使用@RequiredArgsConstructor
可以代替@Autowrited注解;而@RequiredArgsConstructor
是根据构造器注入的,所以会有循坏依赖的问题。
@RequiredArgsConstructor循环依赖问题解决措施
有三种方式可以解决:
- 改为使用@Autowired注解做属性方法注入Bean;
不过,Spring 从 4.0 开始, 就不推荐使用属性注入模式了,原因在于它可以让我们忽略掉一些代码可能变坏的隐患。 - 使用@RequiredArgsConstructor(onConstructor =@_(@Autowired) ),这样默认都是通过@Autowired注入Bean的;
- 使用@RequiredArgsConstructor(onConstructor_={@Lazy} ),做懒加载处理。
No qualifying bean of type ‘java.lang.String‘ available: expected at least 1 bean which qualifies相关推荐
- No qualifying bean of type ‘java.lang.String‘ available expected
错误提示: java.lang.IllegalStateException: Failed to load ApplicationContextat org.springframework.test. ...
- Consider defining a bean of type ‘java.lang.String‘ in your configuration
Consider defining a bean of type 'java.lang.String' in your configuration 总结了网上的几种解决方案: 1.多余的@autowi ...
- springboot启动报错Parameter 0 of method a in com.* required a bean of type 'java.lang.String' that could
springboot服务启动报错,报错信息如下 *************************** APPLICATION FAILED TO START ******************** ...
- 解决 No converter found capable of converting from type [java.lang.String] to type ... 的问题
目录 问题 分析问题 解决问题 问题 今天在项目启动类SuperJsonManagerApplication中,加上这行代码@MapperScan("com.**.mapper") ...
- Failed to convert property value of type java.lang.String to required type java.lang.Integer for pro
Failed to convert property value of type java.lang.String to required type java.lang.Integer for pro ...
- Property ‘id‘ not found on type java.lang.String问题解决
Property 'id' not found on type java.lang.String问题解决 参考文章: (1)Property 'id' not found on type java.l ...
- javax.el.PropertyNotFoundException: Property 'xxx' not found on type java.lang.String
这个错误应该是你从处理器里把数据展示给页面的时候出现的,而且用到了jstl表达式,比如: 此时出现 javax.el.PropertyNotFoundException: Property 'xxx ...
- Failed to convert value of type 'java.lang.String' to required type 'java.util.Date
异常原因:Controller层获取JSP页面请求参数是String类型,而在Controller层接收时使用Date类型,属于方法参数类型不匹配异常 警告: Failed to bind reque ...
- spring:Failed to convert property value of type ‘java.lang.String‘ to required type ‘java.util.Date‘
前言 springboot有接口日期转换的经典问题,给Entity加@JsonFormat解决了输出json日期格式的输入输出问题,但是解决不了非@RequestBody/也就是普通表单提交的日期格式 ...
最新文章
- Android 多线程-----AsyncTask详解
- nmap脚本(nse)使用总结
- 硬盘录像机和服务器,硬盘录像机和视频监控服务器
- 第九讲 二阶齐次常系数线性ODE
- [云炬python3玩转机器学习笔记] 3-3Numpy数据基础
- linux加密框架 crypto 算法管理 - 算法查找接口 crypto_find_alg
- C++工作笔记-C++中assert的作用
- 数据库连接失败报错com.mysql.cj.jdbc.exceptions.CommunicationsException
- Intel 45 纳米处理器加速VMware虚拟架构普及
- 博格和他的先锋集团创业史(2):我觉得自己在天堂
- 简单对抗神经网络GAN实现与讲解-图片对抗
- ​什么是bug?bug的源头在哪里?
- 算法基础14 —— 图论入门之弗洛伊德算法(Floyed + Dijkstra + Bellman-Ford + SPFA)
- 树模型与python实现
- 舵机 - 什么是舵机
- Latex证明环境:白方块/黑方块
- 计算机网络正常无法打开网页,电脑网络正常但是网页无法打开怎么样解决
- 文件上传漏洞揭密剖析(一)-文件上传漏洞原理
- html浏览器标题闪动,如何实现网页标题的闪动提示
- 2022支付宝集五福活动开始了 有哪些集福方法你知道吗?