为什么Spring在没有找到默认构造函数时抛出异常

时间:2014-06-19 06:30:08

标签: java spring

一个简单的测试购物应用程序,我有两个类服装和优惠。 现在,在调用 formalshirt bean时,它会抛出以下异常

Caused by: org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'DiwaliOffer' defined in class path resource [spring.xml]: Instantiation of bean failed; 
nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [Offers]: No default constructor found; 
nested exception is java.lang.NoSuchMethodException: Offers.<init>()

现在,如果我对Offers构造函数进行评论,则该应用程序将成功运行。我的查询是为什么Spring只在有另一个构造函数时才查找默认构造函数?

服装类

public class Clothing {
    private int price;
    private List<Offers> offer;

    public void setOffer(List<Offers> offer) {
        this.offer = offer;
    }

    public void setPrice(int price) {
        this.price = price;
    }
}

提供课程

public class Offers {
    private int discount;
    private String promocode;

    public Offers(int val1, String val2)
    {
        this.discount=val1;
        this.promocode=val2;
    }

    //public Offers(){} /*Default Constructor added due to Spring Exception as in below */  
    /* Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class No default constructor found */
    /* Caused by: java.lang.NoSuchMethodException: com.test.Shopping.Offers.<init>() */

    public void setDiscount(int discount) {
        this.discount = discount;
    }

    public void setPromocode(String promocode) {
        this.promocode = promocode;
    }
}

Spring.xml

<bean id="formalshirt" class="com.test.Shopping.Clothing">
    <property name="price" value="800"></property>              
    <property name="offer">
        <list>
            <ref bean="DiwaliOffer" />
        </list>
    </property>
</bean>

<bean id="DiwaliOffer" class="com.test.Shopping.Offers">
    <property name="discount" value="10"></property>
    <property name="promocode" value="diwali"></property>
</bean>

5 个答案:

答案 0 :(得分:2)

您需要将Offers的Spring XML配置更改为:

<bean id="DiwaliOffer" class="com.test.Shopping.Offers">
    <constructor-arg value="10"></constructor-arg>
    <constructor-arg value="diwali"></constructor-arg>
</bean>

你配置它的方式,Spring首先尝试调用默认构造函数,然后调用setter。但是当然没有默认的构造函数,因此Spring会报告异常。

如果使用Spring 3+,另一个选择是使用Java Config,而不是XML配置。 你只需要

@Configuration
public class AppConfig {

   //add other beans

   @Bean
   public Offers DiwaliOffer() {
      return new Offers(10, diwali);
   }
}

在您的情况下,如果您没有调用构造函数,Java Config的好处是您的配置甚至无法编译,即。它会提前失败,而不是像XML配置那样迟到失败

Spring对于如何创建bean非常灵活,但你需要声明它将如何完成

答案 1 :(得分:1)

这是因为当您添加parametrize constructor时,您需要通过提供spring参数告诉constructor无效......

这个概念很简单:

在默认的constriuctor情况下,您只需创建像new Test();

这样的对象

当你没有默认而不是参数化构造函数时,你必须创建像new Test1("test")这样的对象;

Class Test{

}

Class Test1{
      Test1(String a){

}
}

Spring方式将是:

<bean id="test1" class="Test1">

<constructor-arg value="Zara"/>
</bean

请查看Spring Doc了解更多详情

答案 2 :(得分:1)

您需要为您的bean属性使用constructor-args,以便它选择非默认构造函数。否则Spring首先创建对象,并且没有任何参数,它必须使用零参数构造函数,然后使用setter设置属性。

要传入构造函数args,请将属性更改为constructor-arg,如下所示:

<bean id="DiwaliOffer" class="com.test.Shopping.Offers">

    <constructor-arg index="0" value="10"/>
    <constructor-arg index="1" value="diwali" />

</bean>

答案 3 :(得分:0)

如果类中有任何constructor,则java编译器不提供默认构造函数。

我们可以看到com.test.Shopping.Clothing能够创建实例而com.test.Shopping.Offers能够创建实例。

要创建实例,您需要传递constructor-arg discountpromocode的{​​{1}}。

<bean id="DiwaliOffer" class="com.test.Shopping.Offers">
    <constructor-arg value="10"></property>
    <constructor-arg value="diwali"></property>
</bean>

答案 4 :(得分:0)

你可以这样做:

<bean id="DiwaliOffer" class="com.test.Shopping.Offers" >
    <constructor-arg type="int" value="10" />
    <constructor-arg type="java.lang.String" value="Diwali"/>
</bean>

bean元素中的constructor-arg元素用于通过构造函数注入设置属性值。由于User bean类中只有一个构造函数,因此该代码可以正常工作。