Почему Spring генерирует исключения, когда конструктор по умолчанию не найден

#java #spring

#java #spring

Вопрос:

Простое тестовое приложение для покупок, в котором у меня есть два класса одежды и предложений. Теперь при вызове компонента formalshirt он выдает следующее исключение

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

Теперь, если я прокомментирую конструктор предложений, приложение будет успешно запущено. Мой вопрос в том, почему 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>
  

Ответ №1:

Вам необходимо изменить конфигурацию Spring XML Offers на:

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

В соответствии с тем, как вы его настроили, Spring сначала пытается вызвать конструктор по умолчанию, а затем вызвать установщики. Но, конечно, конструктора по умолчанию нет, и поэтому Spring сообщает об исключении.

Другой вариант, если вы используете Spring 3 , — использовать Java Config вместо XML config. Вы бы просто

 @Configuration
public class AppConfig {

   //add other beans

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

В вашем случае Java Config имеет то преимущество, что ваша конфигурация даже не будет компилироваться, если вы не вызывали конструктор, т.Е. это приведет к преждевременному сбою, а не к позднему сбою, как в конфигурации XML

Spring чрезвычайно гибок в том, как он создает компоненты, но вам нужно объявить, как это будет сделано

Комментарии:

1. да, spring вызывает конструктор по умолчанию, но если я прокомментирую конструктор public Offers(int val1, String val2), то почему он все еще не вызывает конструктор по умолчанию?

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

Ответ №2:

Вам нужно использовать constructor-args для ваших свойств компонента, чтобы он выбирал конструктор, отличный от конструктора по умолчанию. В противном случае Spring сначала создает объект и без каких-либо параметров должен использовать конструктор с нулевым аргументом, а затем устанавливает свойства с помощью сеттеров.

Чтобы передать аргументы конструктора, измените свойство на constructor-arg следующим образом:

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

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

</bean>
  

Ответ №3:

Это потому, что при добавлении вам parametrize constructor нужно указать spring intanitate, указав constructor аргумент…

Концепция проста:

в случае конструктора по умолчанию вы просто создадите объект, подобный new Test() ;

где, как и когда у вас нет конструктора по умолчанию, а есть конструктор параметризации, вам нужно создать объект, подобный new Test1("test") ;

 Class Test{

}

Class Test1{
      Test1(String a){

}
}
  

Весенний путь будет:

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

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

Пожалуйста, посмотрите Spring Doc для получения более подробной информации

Ответ №4:

Если в классе есть какие-либо constructor доступные, то компилятор java не предоставляет конструктор по умолчанию.

И мы видим com.test.Shopping.Clothing , что можем создать экземпляр и com.test.Shopping.Offers не можем.

Чтобы создать экземпляр, вам нужно передать constructor-arg discount и promocode .

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

Комментарии:

1. я понимаю, что классу нужен экземпляр, но он не искал ни одного экземпляра, когда у меня был класс предложений без определенного конструктора

2. вы видите ту же конфигурацию, в которой работает класс предложений ниже

3. public class Offers { private int discount; private String promocode; public void setDiscount(int discount) { this.discount = discount; } public void setPromocode(String promocode) { this.promocode = promocode; } }

4. В этом случае вам необходимо создать конструктор по умолчанию

Ответ №5:

Вы можете сделать :

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

Элемент constructor-arg в элементе bean используется для установки значения свойства посредством внедрения конструктора. Поскольку в классе User bean есть только один конструктор, этот код будет работать нормально.