使用 Spring 注释 @Autowired 的构造函数注入不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10242004/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:05:31  来源:igfitidea点击:

Constructor injection using Spring annotation @Autowired does not work

springannotationsdefault-constructorconstructor-injection

提问by Kaushik Lele

I have created 2 simple classes. Constructor of one class is annotated as @Autowired. It accepts the object of another class. But this code fails.

我创建了 2 个简单的类。一个类的构造函数被注释为@Autowired。它接受另一个类的对象。但是这段代码失败了。

Classes :- 1) SimpleBean.java

类:- 1) SimpleBean.java

@Configuration
public class SimpleBean {
  InnerBean prop1;

  public InnerBean getProp1() {
    return prop1;
  }

  public void setProp1( InnerBean prop1) {
    System.out.println("inside setProp1 input inner's property is "
        + prop1.getSimpleProp1());
    this.prop1 = prop1;
  }

  @Autowired(required=true)
  public SimpleBean(InnerBean prop1) {
    super();
    System.out.println("inside SimpleBean constructor inner's property is "
        + prop1.getSimpleProp1());
    this.prop1 = prop1;
  }
}

2) Inner.java

2) 内部.java

@Configuration
public class InnerBean {
  String simpleProp1;

  public String getSimpleProp1() {
    return simpleProp1;
  }

  public void setSimpleProp1(String simpleProp1) {
    this.simpleProp1 = simpleProp1;
  }

}

When I try to load ApplicationConext

当我尝试加载 ApplicationContext

ApplicationContext acnxt = new AnnotationConfigApplicationContext("com.domain");

It gives following error :-

它给出了以下错误:-

Exception in thread "main" org.springframework.beans.factory.BeanCreationException:         Error creating bean with name 'simpleBean' defined in file [C:\Users\owner\Documents\Java Project\MyWorkSpace\springMVCSecond\WebContent\WEB-INF\classes\com\domain\SimpleBean.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.domain.SimpleBean$$EnhancerByCGLIB$bc418be]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.domain.SimpleBean$$EnhancerByCGLIB$bc418be.<init>()
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:965)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:911)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:75)
at com.test.SpringAnnotationTest.main(SpringAnnotationTest.java:12)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.domain.SimpleBean$$EnhancerByCGLIB$bc418be]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.domain.SimpleBean$$EnhancerByCGLIB$bc418be.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:70)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:958)
... 12 more
Caused by: java.lang.NoSuchMethodException: com.domain.SimpleBean$$EnhancerByCGLIB$bc418be.<init>()
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.getDeclaredConstructor(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:65)
... 13 more

If I introduce no-arg constructor in SimpleBean class. It does not give error. But this does not give me pre-poulated object of SimpleBean ( as in XML configuration using < constructor-arg > ). So when using annotation, is it mandatory to have no-arg constructor ? What is the appropriate way out ?

如果我在 SimpleBean 类中引入无参数构造函数。它不会出错。但这并没有给我预先填充的 SimpleBean 对象(如在 XML 配置中使用 < constructor-arg > )。那么在使用注解时,是否必须有无参数构造函数?什么是合适的出路?

回答by artbristol

From the javadoc of @Configuration:

来自 的javadoc @Configuration

 Configuration is meta-annotated as a {@link Component}, therefore Configuration
 classes are candidates for component-scanning and may also take advantage of
 {@link Autowired} at the field and method but not at the constructor level.

So you'll have to find some other way to do it, unfortunately.

因此,不幸的是,您必须找到其他方法来做到这一点。

回答by beny23

I believe you are mixing up the @Configurationand @Componentannotation. As per the spring docs, @Configurationis used to create beans using Java code (any methods annotated with @Beancreate a bean, whereas classes annotated with @Componentare automatically created..

我相信您正在混淆@Configuration@Component注释。根据spring 文档@Configuration用于使用 Java 代码创建 bean(任何用@Beancreate bean注释的方法,而用注释的类@Component是自动创建的..

I hope the following illustrates this:

我希望以下内容可以说明这一点:

InnerBean.java:

内部Bean.java:

// this bean will be created by Config
public class InnerBean {
  String simpleProp1;

  public String getSimpleProp1() {
    return simpleProp1;
  }

  public void setSimpleProp1(String simpleProp1) {
    this.simpleProp1 = simpleProp1;
  }
}

SimpleBean.java:

SimpleBean.java:

// This bean will be created because of the @Component annotation, 
// using the constructor with the inner bean autowired in
@Component
public class SimpleBean {
  InnerBean prop1;

  public InnerBean getProp1() {
    return prop1;
  }

  @Autowired(required = true)
  public SimpleBean(InnerBean prop1) {
    this.prop1 = prop1;
  }
}

OuterBean.java

外部Bean.java

// this bean will be created by Config and have the SimpleBean autowired.
public class OuterBean {
  SimpleBean simpleBean;

  @Autowired
  public void setSimpleBean(SimpleBean simpleBean) {
    this.simpleBean = simpleBean;
  }

  public SimpleBean getSimpleBean() {
    return simpleBean;
  }
}

Config.java

配置文件

// this class will create other beans
@Configuration
public class Config {
  @Bean
  public OuterBean outerBean() {
    return new OuterBean();
  }

  @Bean
  public InnerBean innerBean() {
    InnerBean innerBean = new InnerBean();
    innerBean.setSimpleProp1("test123");
    return innerBean;
  }
}

Main.java:

主.java:

public class Main {
  public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext("com.acme");
    OuterBean outerBean = ctx.getBean("outerBean", OuterBean.class);
    System.out.println(outerBean.getSimpleBean().getProp1().getSimpleProp1());
  }
}

The main class uses the AnnotationConfigApplicationContextto scan for both @Configurationand @Componentannotations and create the beans accordingly.

主类使用AnnotationConfigApplicationContext来扫描@Configuration@Component注释并相应地创建 bean。