Spring报no qualifying bean of type String可用错误排查
报错原因
这个错误本质是Spring在实例化托管Bean时,需要注入java.lang.String类型的依赖,但IoC容器中没有匹配的String类型Bean,结合给出的代码,触发场景基本是以下两种:
- 场景1:
Vehicle类被Spring直接扫描实例化,没有走定义的@Bean创建逻辑。如果不小心给Vehicle类加了@Component/@Service等组件注解,或是配置了额外的类路径扫描规则把Vehicle识别成了托管组件,Spring会调用Lombok生成的全参构造器public Vehicle(String model)创建实例,此时会自动找容器里的String类型Bean注入给model参数,找不到就抛出NoSuchBeanDefinitionException。 - 场景2:
Test配置类被Lombok生成了带String参数的构造器。如果给Test类加了@AllArgsConstructor,或是给val字段加了final修饰同时类上有@RequiredArgsConstructor注解,Lombok会生成参数为String val的有参构造函数。Spring 4.3之后实例化Bean时,如果类只有一个有参构造器,会默认使用这个构造器执行依赖注入,不会走@Value字段注入逻辑,此时容器中没有String类型的Bean就会触发报错。
解决方案
对应触发原因逐个修复即可:
- 检查
Vehicle类:去掉类上多余的@Component等组件注解,保证Vehicle实例只通过@Bean方法创建,不要让Spring直接扫描实例化该类。 - 检查
Test配置类:不要给配置类加任何Lombok构造器相关注解(@AllArgsConstructor/@NoArgsConstructor/@RequiredArgsConstructor),保证配置类有公开的无参构造函数,让@Value的字段注入逻辑正常执行。 - (稳妥写法)把
@Value直接写到@Bean方法的参数上,完全规避配置类字段注入的时序问题,示例代码如下:
@Configuration public class Test { @Bean public Vehicle getVehicle(@Value("${value}") String val) { return new Vehicle(val); } }
- (最佳实践)如果是读取自定义配置,优先使用
@ConfigurationProperties做批量绑定,不要零散使用@Value注入,从根源避免同类注入问题:
// 配置绑定类 @ConfigurationProperties(prefix = "") // 配置写在yaml根路径,prefix留空即可 @Component @Getter @Setter public class AppConfig { private String value; private Integer price; } // 配置类中注册Bean @Configuration public class Test { @Bean public Vehicle getVehicle(AppConfig appConfig) { return new Vehicle(appConfig.getValue()); } }
内容的提问来源于stack exchange,提问作者Shankar
相关产品推荐
相关产品推荐

