Spring不使用@Autowired进行多构造器注入时Bean实例化失败问题求助
我现在尝试使用构造器注入,之前理解的逻辑是当Spring发现多个构造器时,会选择参数数量最多且参数类型都能匹配Spring管理Bean的那个构造器。但在下面的例子里却失败了,按道理应该调用第二个构造器才对,结果却报了找不到默认构造器的错误,想请教大家这是怎么回事?
我的代码如下:
package autowiring; import org.springframework.stereotype.Component; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @Configuration @ComponentScan class config{ } @Component public class comp1{ Foo ab; Boo bo; public comp1(Foo ab,String a,X d){ System.out.println("constructor 1 called"); this.ab=ab; } public comp1(Foo ab,Boo bo){ System.out.println("constructor 2 called"); this.ab=ab; this.bo=bo; } public static void main(){ var ctx=new AnnotationConfigApplicationContext(config.class); } } @Component class Foo{ String name="Foo"; } @Component class Boo{ String name="Bar"; } class X{ }
运行后得到的输出/报错:
amdi@debian:~/Documents/learn/java2/test$ java -jar target/my*.jar Feb 18, 2025 6:39:04 AM org.springframework.context.support.AbstractApplicationContext refresh WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'comp1' defined in URL [jar:file:/home/lmhamdi/Documents/learn/java2/test/target/my-app-1.0.0.jar!/autowiring/comp1.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [autowiring.comp1]: No default constructor found; nested exception is java.lang.NoSuchMethodException: autowiring.comp1.<init>() Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'comp1' defined in URL [jar:file:/home/lmhamdi/Documents/learn/java2/test/target/my-app-1.0.0.jar!/autowiring/comp1.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [autowiring.comp1]: No default constructor found; nested exception is java.lang.NoSuchMethodException: autowiring.comp1.<init>() at org.springframe
问题分析与解决方案
核心原因
你之前对Spring构造器注入的规则理解有误,再加上代码里的小细节问题,导致了这个错误:
主方法定义不规范:标准Java主方法必须是
public static void main(String[] args),你写的public static void main()不符合JVM规范,虽然这不是Bean创建失败的直接原因,但会导致程序无法通过JVM正常启动(从你的报错来看,你应该是通过Maven等工具运行的)。Spring构造器选择规则误解:
- 在Spring 4.3之前,没有
@Autowired标注的话,Spring默认会尝试使用无参构造器创建Bean - 即使是Spring 4.3+,当存在多个构造器且没有任何一个被
@Autowired标注时,Spring依然会优先寻找无参构造器,找不到就会报错,而不是自动选择参数都匹配的构造器!只有当类中只有一个构造器时,Spring才会自动注入该构造器的参数,无需@Autowired。
- 在Spring 4.3之前,没有
解决办法
你可以通过以下几种方式解决:
方式一:用@Autowired指定要使用的构造器
在你希望Spring调用的第二个构造器上添加@Autowired注解,明确告诉Spring使用这个构造器:@Autowired public comp1(Foo ab,Boo bo){ System.out.println("constructor 2 called"); this.ab=ab; this.bo=bo; }方式二:删除多余构造器
如果你不需要第一个构造器,直接删除它,这样Spring 4.3+会自动使用唯一的构造器进行注入,无需额外标注@Autowired。方式三:添加无参构造器(不推荐)
给comp1添加一个无参构造器,Spring就能创建实例,但这种方式不符合构造器注入的最佳实践,因为会创建未注入依赖的空实例,后续可能需要配合setter注入,不建议使用。
另外,提醒一下:Java类名应该遵循首字母大写的规范,比如comp1建议改成Comp1,config改成Config,这样代码可读性会更好。
备注:内容来源于stack exchange,提问作者samh

