3

简化代码(我使用的是 Spring 3.1.4)。

这是我想要自动装配的一个类:

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

这就是我尝试获取 bean 的方式:

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

问题:

  • 为什么我需要一个默认构造函数?我不希望它被调用。
  • 出于某种原因,我在课堂上是否需要“@Component”?我看到其他人这样做
  • 为什么这段代码可以通过我的 junit 测试工作(据我所知)?(我如何运行它们如下所示。

这是运行单元测试的片段:

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

2 回答 2

3

由于您没有空的构造函数,因此您必须指定构造函数参数,以便 Spring 构造函数解析工作......

例如

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 来显式指定参数

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

- - - - - - - - - - - - - - - 更新 - - - - - - - - - - ------------

如果您想避免手动添加构造函数参数..您可以尝试使用自动装配它们

<bean name="GreatBean" class="mypackage.MyCoolClass" autowire="constructor" />
于 2013-07-18T22:21:51.457 回答
2

答案(几个小时后)是使用:

AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx);

在读取 bean 定义之后,但在第一次刷新上下文之前。这让我得到了我想要的(构造函数自动装配),而无需触及我的 XML 或我的类定义。它也将很好地扩展(将来我可以像上面一样继续编写 XML 和类,并且不需要更改任何内容。最后的代码是:

GenericApplicationContext ctx = new GenericApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new ClassPathResource("config.xml"));
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx);
ctx.refresh();
于 2013-07-19T00:34:06.967 回答