Зачем мне нужен сеттер для autowired/injected поля?

У меня есть боб:

    <bean id="BasketLogic" class="efco.logic.EfcoBasketLogic" autowire="byType">
        <property name="documentLogic" ref="DocumentLogic" />
        <property name="stateAccess" ref="StateAccess" />
        <property name="contextAccess" ref="ContextAccess" />
    </bean>

  <bean id="EfcoErpService" autowire="byType" class="efco.erp.service.EfcoErpServiceImpl">
    <constructor-arg ref="ErpConnector"/>
  </bean>

documentLogic, stateAccess и contextAccess — это поля в BasketLogicImpl.

А у меня нет <context:component-scan />

EfcoBasketLogic.java:

public class EfcoBasketLogic extends BasketLogicImpl {

        @Inject
        private EfcoErpService erpService;
    ...
    ...
    ...
}

erpService имеет значение null, если я не укажу установщик. Но почему? Я думал, что сеттер не нужен там, где происходит автопроводка? Может быть за это отвечает BasketLogicImpl?


person GarfieldKlon    schedule 02.11.2012    source источник


Ответы (3)


Вам нужно использовать сеттер, потому что аннотации не обнаруживаются, если Spring не сообщает об этом через <context:component-scan /> или <context:annotation-config />. Сеттер обнаружен, потому что вы указали autowire="byType".

Вы также можете найти этот вопрос и ответ полезным: Весна

person mrembisz    schedule 02.11.2012
comment
Если я это сделаю, появится новая проблема --› Не определен ни один уникальный bean-компонент типа [xyz]: ожидается один соответствующий bean-компонент, но найдено 5. Это вызвано другим bean-компонентом, в котором я явно ввожу свойство через <property name="x" ref="y">, и есть 5 bean-компонентов, которые реализуют этот интерфейс. Свойство x имеет аннотацию @Inject. Итак, кажется, что явное определение не отменяет автосвязывание? - person GarfieldKlon; 02.11.2012
comment
@Inject будет разрешен правильно, если есть только один bean-компонент данного типа или один, помеченный как основной. Если у вас есть несколько взаимозаменяемых bean-компонентов этого типа, вам нужно вводить их по имени, используя @Resource или xml. - person mrembisz; 02.11.2012
comment
Даже если я явно введу этот компонент через <property name="..." ref="..."> ? - person GarfieldKlon; 02.11.2012
comment
Рекомендую задать еще вопрос. Я ответил на ваш первоначальный вопрос и не могу понять, в чем ваша следующая проблема, без более подробного описания, включая некоторый код или xml. - person mrembisz; 02.11.2012
comment
Мой вопрос заключался в том, почему я должен писать сеттер (когда я не использую компонент-сканирование или аннотацию-конфигурацию). - person GarfieldKlon; 02.11.2012
comment
Хорошо, но зачем мне писать сеттер, если я использую autowire=byType и аннотирую поле @Inject? Это предназначено, путь? Я имею в виду, что я могу выбросить сеттер, если буду использовать annotation-config. Так есть ли разница между ним и autowire=byType? - person GarfieldKlon; 02.11.2012
comment
Autowiring обнаруживает сеттеры и параметры конструктора как потенциальные зависимости. Не частные поля. Аннотации невидимы, если вы не требуете их проверки. - person mrembisz; 02.11.2012

Прежде всего, использование <context:component-scan /> или <context:annotation-config /> позволяет Spring сканировать ваш код на наличие подходящих bean-компонентов для соответствия зависимостям, что значительно улучшит его способность правильно подключать их, поэтому я предлагаю добавить их в ваш файл контекста.

Во-вторых, вы должны знать, что @Inject является стандартной (имеется в виду спецификация JSR-330) аннотацией. Можно смешивать и сопоставлять аннотации Spring со стандартными, но при этом поведение может отличаться. @Named обычно сочетается с @Inject для сопоставления компонентов с зависимостями (оба JSR-330). См. этот справочный материал. для получения подробной информации и см. Таблицу 4.6 для комментариев по использованию.

Но чтобы прямо ответить на ваш вопрос, "зачем мне нужен установщик, если не используется сканирование компонентов", потому что вы не используете сканирование компонентов. Вы просите Spring внедрить зависимость "byType", но не позволяете Spring сканировать ваш код на наличие компонентов этого типа. Причина, по которой сеттер работает, заключается в том, что тип вводимого аргумента сеттера может быть обнаружен Spring в скомпилированном байт-коде (т.е. метаданных), и поэтому он успешно разрешает ваш запрос.

person pmhargis    schedule 03.09.2013
comment
К вашему сведению: при использовании ` ‹context:component-scan /› ` убедитесь, что вы установили атрибут base-package в корне вашей иерархии классов, где объявлены классы компонентов (через @Named или @Autowired). Например: ‹beans› ‹context:component-scan base-package=org.example/› ‹/beans› - person pmhargis; 03.09.2013

Насколько я понимаю, конфигурация XML переопределяет конфигурацию аннотации. Тот факт, что указанный autowire="byType" переопределяет автоматическую инъекцию, которая ищет наличие метода установки для внедрения зависимости.

person kbk    schedule 13.04.2016