2013-07-18 3 views
2

Упрощенный код (я использую Spring 3.1.4).Ошибка конструктора Spring @Autowired и @Qualifier

Вот класс, который я хочу autowired:

public class MyCoolClass { 

    @Autowired 
    public MyCoolClass(
     @Qualifier("CoolBean1") SomeOtherClass1 foo1, 
     @Qualifier("CoolBean2") SomeOtherClass1 foo2 
    ) { 
     this.foo1 = foo1; 
     this.foo2 = foo2; 
    } 

    // ... 
} 

Вот моя весна конфигурации XML:

<bean name="CoolBean1" class="mypackage.SomeOtherClass1"/> 
<bean name="CoolBean2" class="mypackage.SomeOtherClass1"/> 
<bean name="GreatBean" class="mypackage.MyCoolClass"/> 

И вот как я пытаюсь получить боб:

GenericApplicationContext ctx = new GenericApplicationContext(); 
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx); 
xmlReader.loadBeanDefinitions(new ClassPathResource("config.xml")); 
ctx.refresh(); 

В момент, когда я звоню, я сталкиваюсь с этим:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'GreatBean' defined in class path resource [config.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [mypackage.MyCoolClass]: No default constructor found; nested exception is java.lang.NoSuchMethodException: mypackage.MyCoolClass.<init>() 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:997) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:943) 
     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:294) 
     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) 
     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) 
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607) 
     at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925) 
     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472) 
     at mypackage.Runner.main(Runner.java:234) 

Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [mypackage.MyCoolClass: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.amazon.maxis.security.gbac.AsynchronousFolderAuthorizationManager.<init>() 
     at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:990) 
     ... 11 more 

Caused by: java.lang.NoSuchMethodException: mypackage.MyCoolClass.<init>() 
     at java.lang.Class.getConstructor0(Class.java:2800) 
     at java.lang.Class.getDeclaredConstructor(Class.java:2043) 
     at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78) 
     ... 12 more 

Вопросы:

  • Почему мне нужно construtor по умолчанию? Я бы не хотел, чтобы это называлось.
  • Нужно ли мне «@Component» по какой-то причине в классе? Я вижу, что другие делают это
  • Почему этот код работает (насколько я могу судить) через мои тесты на junit? (Как я бегу они показаны ниже

Вот фрагмент кода для выполнения модульных тестов:.

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations={"classpath:config.xml"}) 
public class MyJunitTest { 
    //... 
} 
+0

У вас есть пустой конструктор ? –

+0

@MartinSpa Нет, я этого не делаю. Я также не хочу его реализовывать. –

+0

На самом деле, может быть, вам не обязательно. Просто определяя bean-компоненты в xml, используйте конструктор-arg также для параметров в вашем конструкторе, http://stackoverflow.com/a/10649348/228692 –

ответ

2

ответ на этот вопрос (в часах позже) использовать:

AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx); 

После определения видов бобов был прочитан, но до того, как контекст был обновлен в первый раз. Это дает мне то, что я хочу (автоустановка конструктора), не затрагивая ни мой XML, ни мои определения класса. Он также будет масштабироваться хорошо (в будущем я могу продолжать писать XML и классы так же, как выше, и не нужно будет ничего менять Окончательный бит кода, который работал было:.

GenericApplicationContext ctx = new GenericApplicationContext(); 
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx); 
xmlReader.loadBeanDefinitions(new ClassPathResource("config.xml")); 
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx); 
ctx.refresh(); 
+0

Приятно, вы также можете достичь этого, добавив '' в свой файл конфигурации. –

3

Поскольку вы не пустой конструктор, необходимо указать конструктору-арг, для Весна разрешение конструктор работать ...

Например

package examples; 

public class ExampleBean { 

    private int years;    //No. of years to the calculate the Ultimate Answer 
    private String ultimateAnswer; //The Answer to Life, the Universe, and Everything 

    public ExampleBean(int years, String ultimateAnswer) { 
     this.years = years; 
     this.ultimateAnswer = ultimateAnswer; 
    } 
} 

вы можете явно указать арг, определив боб следующим

<bean id="exampleBean" class="examples.ExampleBean"> 
    <constructor-arg type="int"><value>7500000</value></constructor-arg> 
    <constructor-arg type="java.lang.String"><value>42</value></constructor-arg> 
</bean> 

----------------------------- UPDATE ------------- -------------------

Если вы хотите, чтобы избежать добавления конструктора-арг вручную .. вы можете попробовать их с помощью автоматического связывания

<bean name="GreatBean" class="mypackage.MyCoolClass" autowire="constructor" /> 
Смежные вопросы