【问题标题】:Constructor injection using Spring annotation @Autowired does not work使用Spring注解@Autowired的构造函数注入不起作用
【发布时间】:2012-05-01 18:57:08
【问题描述】:

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

类:- 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) 内部.java

@Configuration
public class InnerBean {
  String simpleProp1;

  public String getSimpleProp1() {
    return simpleProp1;
  }

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

}

当我尝试加载 ApplicationConext 时

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

它给出以下错误:-

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$$4bc418be]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.domain.SimpleBean$$EnhancerByCGLIB$$4bc418be.<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$1.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$$4bc418be]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.domain.SimpleBean$$EnhancerByCGLIB$$4bc418be.<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$$4bc418be.<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

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

【问题讨论】:

  • 你想打电话给AnnotationConfigApplicationContext("com.domain") Package吗?请输入您的完整代码。
  • @RaviParekh 是的,这些类在 com.domain 包中。我正在尝试调用 ApplicationContext acnxt = new AnnotationConfigApplicationContext("com.domain");已经提过了。

标签: spring annotations default-constructor constructor-injection


【解决方案1】:

来自@Configuration的javadoc:

 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.

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

【讨论】:

    【解决方案2】:

    我相信您混淆了@Configuration@Component 注释。根据spring docs@Configuration 用于使用 Java 代码创建 bean(任何带有 @Bean 注释的方法都会创建一个 bean,而带有 @Component 注释的类会自动创建..

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

    InnerBean.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:

    // 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

    // 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:

    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());
      }
    }
    

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

    【讨论】:

    • 在我的代码中,我将SimpleBean 和InnerBean 类中的注释从@Configuration 更改为@Component。我仍然遇到同样的错误。它仍在抱怨“未找到默认构造函数”。
    • 我已经测试了我在 Spring 3.0.6 中提供的示例代码,它会打印“test123”。你用的是哪个版本的spring?您可能希望显示更多配置,因为类名称 com.domain.SimpleBean$$EnhancerByCGLIB$$4bc418be.&lt;init&gt;() 表明涉及更多代理。
    • 我仅使用 spring 3.0.6 jar 对其进行了测试。当我用@component而不是@configuration标记类时;它有类似的错误。只有CGLIB部分没有参与。
    • 你能通过尝试运行我的代码来检查吗?带有@Configuration 的类和一次带有@Component 的类。
    • 我已经运行了你的代码,它会打印:inside SimpleBean constructor inner's property is null(使用@Component
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    相关资源
    最近更新 更多