Автопроводка не происходит, если есть другой бин того же класса со свойством, установленным вручную - PullRequest
7 голосов
/ 28 февраля 2012

Я хочу создать два bean-компонента одного класса через конфигурационный файл xml. У класса есть аннотированный установщик, который будет заполнен весной. В одном из определений бина я также предоставляю значение вручную, чтобы переопределить одно из аннотации. Но когда я делаю это, пружина больше не обрабатывает проводку аннотации.

Ниже приведен минимальный код для демонстрации этого эффекта, для простоты используется @Value, но то же самое с @Autowired:

import org.springframework.beans.factory.annotation.Value;

import javax.annotation.PostConstruct;

public class AutowireTest {
  public String testField;

  @PostConstruct
  public void init() {
    if (testField == null)
      throw new RuntimeException("FAIL");
  }

  @Value("default")
  public void setTestField(String testField) {
    this.testField = testField;
  }
}

и конфигурация пружины:

<bean id="au_test1" class="AutowireTest">
  <property name="testField" value="manual"/>
</bean>

<bean id="au_test2" class="AutowireTest"/>

Если я удаляю <property name="testField" value="manual"/>, оба бина получают «default». Если это там, второй бин бросает исключение. Я взглянул на весенний код, и AutowiredAnnotationBeanPostProcessor используетjectionMetadataCache, где классы являются ключами для метаданных внедрения, то есть установка определенного свойства для одного бина отключает автопроводку для других экземпляров.

Есть идеи, почему это так? Как я могу добиться подобного эффекта, работая не только со строковыми значениями, но и с объектными бинами?

EDIT: Я хочу иметь свойство, где есть несколько подходящих кандидатов. Один помечен как primary. Если я не укажу кандидата вручную через xml, я бы хотел, чтобы основной был подключен. Мой оригинальный подход заключался в использовании @Autowired для этого свойства, но так как это не работает, я ищу альтернативу. По какой-то причине я не хочу использовать наследование бобов.

EDIT2: Если я поменяю местами два определения бина, проблема не возникнет. Свойство автоматически подключается до тех пор, пока не будет обнаружено ручное переопределение в первый раз. Это означает, что это не намеренная функция, так как она может привести к странным и трудным обнаружениям ошибок в некоторых проектах с зависимостями, не связанными должным образом.

Ответы [ 2 ]

1 голос
/ 29 февраля 2012

Если вы посмотрите на javaDocs для AutowiredAnnotationBeanPostProcessor, появится примечание:

"Внедрение аннотации будет выполнено до внедрения XML; последняя конфигурация переопределит первую для свойств проводной через оба подхода. "

Это означает, что установка свойства bean-компонентов в xml с использованием значения свойства «testField» и без него приводит к созданию двух новых bean-компонентов, один из которых имеет значение testField, а другой - нулевое.

Это одна или другая вещь. Вы можете либо использовать автопроводку для класса, либо настроить его вручную в xml, но не можете сделать и то, и другое. Я предполагаю, что когда вы удаляете пружину свойства, вы просто устанавливаете один и тот же bean-компонент с двумя именами.

Как только компоненты одного и того же класса настроены вручную, вы можете добавить их в другие компоненты, используя аннотацию @Qualifier("au_test1")

0 голосов
/ 08 марта 2012

По-моему, это баг весной, который я отправил через jira . Чтобы обойти это, необходимо переместить аннотацию из сеттера в поле. Сеттер должен остаться, чтобы разрешить ручное переопределение свойства. Возможная логика установки (я знаю, что этого следует избегать) должна быть перемещена в @PostConstruct. Адаптированный оригинальный код ниже:

import org.springframework.beans.factory.annotation.Value;

import javax.annotation.PostConstruct;

public class AutowireTest {
  @Value("default")
  public String testField;

  @PostConstruct
  public void init() {
    if (testField == null)
      throw new RuntimeException("FAIL");
  }

  public void setTestField(String testField) {
    this.testField = testField;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...