Spring Boot中同时使用@Component与@Bean注入同一类的异常差异问题
问题描述
我在Spring Boot应用中,给Book类添加了@Component注解,同时在标注@Configuration的AppConfig类中,编写了标注@Bean注解的getBook()方法返回Book对象。原本以为使用@Autowired注入时一定会抛出「required a single bean, but 2 were found」异常,但实际出现了两种不同的情况:
- 使用如下代码注入时,未出现异常:
@Autowired Book book; - 使用如下代码注入时,抛出「required a single bean, but 2 were found」异常:
@Autowired Book obj;
相关代码
1. Book类代码
@Component public class Book { void readBook() { System.out.println("reading book"); } }
2. AppConfig类代码
@Configuration public class AppConfig { @Bean Book getBook() { return new Book(); } }
3. 触发异常的主类代码
@SpringBootApplication public class IntroductionToSpringBootApplication implements CommandLineRunner { @Autowired Book obj; public static void main(String[] args) { SpringApplication.run(IntroductionToSpringBootApplication.class, args); } @Override public void run(String... args) throws Exception { } }
4. 无异常的主类代码
@SpringBootApplication public class IntroductionToSpringBootApplication implements CommandLineRunner { @Autowired Book book; public static void main(String[] args) { SpringApplication.run(IntroductionToSpringBootApplication.class, args); } @Override public void run(String... args) throws Exception { } }
原因分析
这是Spring自动装配的名称匹配优先级导致的:
- 两个
Book类型的bean拥有不同的默认名称:@Component注解生成的bean,默认名称为类名首字母小写,也就是book;@Bean注解的方法,默认bean名称为方法名,也就是getBook。
- 当使用
@Autowired Book book;注入时,Spring会优先尝试按变量名匹配bean名称,刚好存在名称为book的bean(来自@Component),匹配成功,不会触发类型匹配的多bean冲突检查。 - 当使用
@Autowired Book obj;注入时,变量名obj和两个bean的名称都不匹配,Spring会退回到按类型匹配,此时发现存在两个Book类型的bean,就抛出了多bean冲突的异常。
解决建议
如果想要避免这种场景的异常,可以采用以下方式:
- 给
@Bean指定与@Component同名的bean名称:@Bean(name = "book"); - 在其中一个bean上添加
@Primary注解,让Spring在类型匹配时优先选择该bean; - 使用
@Qualifier注解指定要注入的bean名称,比如@Autowired @Qualifier("book") Book obj;。
内容的提问来源于stack exchange,提问作者Code007
相关产品推荐
相关产品推荐

