【问题标题】:Autowired on Constructor with parameters fails?在带有参数的构造函数上自动装配失败?
【发布时间】:2020-05-23 16:36:05
【问题描述】:

我有以下示例代码:

豆类:

package com.example.learn1.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Bean1 {

    private String name;
    private int id;

    public Bean1() {
        System.out.println("Inside Bean1() constructor");
    }

    @Autowired
    public Bean1(String name, int id) {
        System.out.println("Inside Bean1(String name, int id) constructor");
        this.name = name;
        this.id = id;
    }

    public Bean1(String name) {
        System.out.println("Inside Bean1(String name) constructor");
        this.name = name;
    }

    public Bean1(int id) {
        System.out.println("Inside Bean1(int id) constructor");
        this.id = id;
    }

}

以下是主应用程序,这里我正在尝试自动装配 bean1。

package com.example.learn1.main;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import com.example.learn1.bean.Bean1;
@Configuration
@ComponentScan(basePackages = { "com.example.learn1" })
@Component
public class MainApp {

    @Autowired
    Bean1 bean1;

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(MainApp.class);
        System.out.println("Inside main, ctx is --> " + ctx);
        MainApp t = ctx.getBean(MainApp.class);
        t.print();
    }

    public void print() {
        System.out.println("Inside MainApp#print() method");
    }
}

当我不在构造函数public Bean1(String name, int id) 上保留@Autowire 时,程序运行良好。默认情况下,它调用无参数构造函数,即:public Bean1()。我在构造函数public Bean1(String name, int id) 上使用@Autowire 的那一刻,它失败了。

那么它是否只适用于无参数构造函数?我怎样才能使它适用于带参数的构造函数?

谁能帮我理解这种行为?

以下是例外:

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainApp': Unsatisfied dependency expressed through field 'bean1'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bean1' defined in file [/Users/vkoul/eclipse-workspace/spring-framework-learning/target/classes/com/example/learn1/bean/Bean1.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is 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.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
    at com.example.learn1.main.MainApp.main(MainApp.java:37)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bean1' defined in file [/Users/vkoul/eclipse-workspace/spring-framework-learning/target/classes/com/example/learn1/bean/Bean1.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is 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.ConstructorResolver.createArgumentArray(ConstructorResolver.java:769)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:218)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1308)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1154)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1244)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
    ... 14 more
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:1651)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1210)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
    ... 27 more

【问题讨论】:

  • 您能告诉我们例外情况吗?
  • 我想你可以关注stackoverflow.com/a/50604533/4597596,看看如何自动装配和使用参数化构造函数。
  • 你为什么在那个构造函数上使用@Autowired?你到底在课堂上注入了什么?
  • @MehrdadHosseinNejad:我正在尝试在MainApp 中使用@Autowired 创建Bean1。默认情况下,它调用无参数构造函数。我正在检查如何通过调用非参数构造函数来创建这个Bean1。这不可能吗?

标签: spring spring-context


【解决方案1】:
@Autowired
public Bean1(String name, int id) {
    System.out.println("Inside Bean1(String name, int id) constructor");
    this.name = name;
    this.id = id;
}

当构造函数用于实例化bean1时,告诉容器注入2个bean(一个String类型的bean称为name,另一个称为id类型int)。 你在哪里定义了这些bean?另请注意,从原始类型创建 bean 并不常见,这并不意味着您不能。

对于原始类型,我们通常在application.properties 中声明它们,然后使用@Value 注入它们。

【讨论】:

  • 为了简单起见,我保留了原语,我可以很好地保留一些对象。我的问题更倾向于如何使用具有参数的构造函数进行注入。
  • 正如我在回答 Where did you define those beans? 中所说的那样。如果你想注入 bean 作为构造函数参数,你必须先定义它们。因此,定义 2 个 Stringint 类型的 bean,然后它们将被挑选并注入到您的构造函数中。
  • @akumar8:感谢您的意见。所以如果我们在field 上做@Autowired,为什么我们还需要定义constructorsetter method
  • @CuriousMind 在字段上使用@Autowired 时,您不需要setterconstructor。您有 3 种注入 bean 的方式,field injection@Autowiredsetter 注入和 constructor 注入,由您选择一种。
  • 使用field injection时,容器在后台使用默认构造函数构造您的对象,然后设置字段值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-29
  • 2017-03-09
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多