You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring不使用@Autowired进行多构造器注入时Bean实例化失败问题求助

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构造器注入的规则理解有误,再加上代码里的小细节问题,导致了这个错误:

  1. 主方法定义不规范:标准Java主方法必须是public static void main(String[] args),你写的public static void main()不符合JVM规范,虽然这不是Bean创建失败的直接原因,但会导致程序无法通过JVM正常启动(从你的报错来看,你应该是通过Maven等工具运行的)。

  2. Spring构造器选择规则误解:

    • 在Spring 4.3之前,没有@Autowired标注的话,Spring默认会尝试使用无参构造器创建Bean
    • 即使是Spring 4.3+,当存在多个构造器且没有任何一个被@Autowired标注时,Spring依然会优先寻找无参构造器,找不到就会报错,而不是自动选择参数都匹配的构造器!只有当类中只有一个构造器时,Spring才会自动注入该构造器的参数,无需@Autowired。

解决办法

你可以通过以下几种方式解决:

  • 方式一:用@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:34:50