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

#java #spring

#java #весна

Вопрос:

Можем ли мы внедрить служебный компонент без конструктора по умолчанию в контроллер?

У меня есть следующий контроллер

 @Controller
public class ArticleController {
    @Autowired
    private WithConstructorService withConstructorService;
    ...
}
  

И мой сервис:

 @Service
public class WithConstructorServiceImpl implements WithConstructorService {
    String name;
    String address;

    public WithConstructorServiceImpl(String name, String address) {
        super();
        this.name = name;
        this.address = address;
    }
}
  

Я получаю исключение

 SEVERE: Servlet /springheat threw load() exception
java.lang.NoSuchMethodException:  WithConstructorServiceImpl.<init>()
  

Обновить:

Я делаю предположение здесь, но можем ли мы сделать какую-то магию AOP и по-прежнему использовать метод аннотированного конструктора arg service?

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

1. технически, это не java «bean», если у него нет конструктора по умолчанию.

2. Я упоминал об этом с точки зрения spring bean.

Ответ №1:

Если вы используете spring 3, вы можете использовать @Value аннотацию для подключения полей name и address, и тогда их не нужно устанавливать через конструктор. Или не используйте @Service аннотацию и вместо этого объявите свой компонент в xml с соответствующими <constructor-arg> тегами.

В любом случае, контейнер spring должен знать, где получить значения для name и address, иначе он не сможет создать ваш WithConstructorServiceImpl .

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

1. Я делаю предположение здесь, но можем ли мы использовать некоторую магию AOP и по-прежнему использовать метод службы аннотированного конструктора arg ?… обновил вопрос тем же запросом.

Ответ №2:

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

Первая возможность: автоматическое подключение двух аргументов:

 @Autowired
public WithConstructorServiceImpl(@Qualifier("theNameBean") String name, 
                                  @Qualifier("theAdressBean") String address) {
  

В этом случае вам нужно будет объявить два компонента типа String в context.xml файл с соответствующим именем.

Вторая возможность: объявить сам компонент в context.xml файл и сообщите Spring, какие аргументы он должен передать конструктору.

См. http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-collaborators

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

1. Не могли бы вы поделиться, как объявить «два компонента типа string в context.xml » для полноты картины?

Ответ №3:

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

Что вы можете сделать, так это просто создать сеттеры для name и address, а затем добавить их к введенному компоненту.