Внедрение конструктора с использованием аннотации Spring @Autowired не работает

Я создал 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 с использованием ‹ конструктор-аргумент >). Итак, при использовании аннотации обязательно ли иметь конструктор без аргументов? Каков правильный выход?


person Kaushik Lele    schedule 20.04.2012    source источник
comment
Вы пытаетесь позвонить как AnnotationConfigApplicationContext("com.domain") Package? Пожалуйста, введите свой полный код.   -  person Ravi Parekh    schedule 20.04.2012
comment
@RaviParekh да, эти классы находятся в пакете com.domain. И я пытаюсь вызвать ApplicationContext acnxt = new AnnotationConfigApplicationContext(com.domain); Это уже упоминалось.   -  person Kaushik Lele    schedule 21.04.2012


Ответы (2)


Из 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.

Так что, к сожалению, вам придется найти какой-то другой способ сделать это.

person artbristol    schedule 20.04.2012

Я полагаю, вы путаете аннотацию @Configuration и @Component. Согласно документам Spring, @Configuration используется для создания bean-компонентов с использованием кода Java (любые методы, аннотированные @Bean, создают bean-компонент, тогда как классы, аннотированные @Component создаются автоматически..

Я надеюсь, что следующее иллюстрирует это:

Внутренний компонент.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;
  }
}

Конфиг.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;
  }
}

Основная.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-компонентов.

person beny23    schedule 20.04.2012
comment
В моем коде я изменил аннотацию с @ Configuration на @ Component как в классах SimpleBean, так и InnerBean. Тем не менее я получаю ту же ошибку. Он все еще жалуется, что конструктор по умолчанию не найден. - person Kaushik Lele; 20.04.2012
comment
Я протестировал пример кода, который я предоставил с Spring 3.0.6, и он печатает test123. Какую версию весны вы используете? Вы можете захотеть показать больше своей конфигурации, потому что имя класса com.domain.SimpleBean$$EnhancerByCGLIB$$4bc418be.<init>() предполагает наличие других прокси-серверов. - person beny23; 20.04.2012
comment
Я тестировал его, используя только банки Spring 3.0.6. Когда я отметил классы компонентом @ вместо конфигурации @; была похожая ошибка. Только часть CGLIB не была задействована. - person Kaushik Lele; 21.04.2012
comment
Вы можете проверить, запустив мой код. Классы с @Configuration и один раз с @Component. - person Kaushik Lele; 21.04.2012
comment
Я запустил ваш код, и он печатает: inside SimpleBean constructor inner's property is null (используя @Component) - person beny23; 23.04.2012