#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 есть только один конструктор, этот код будет работать нормально.