Вопрос о квалификации в Spring DI - PullRequest
4 голосов
/ 16 марта 2011

Обычно квалифицированный компонент добавляется в аннотированные поля с таким же квалификатором:

@Component        class Apple1 implements IApple {}
@Component @Black class Apple2 implements IApple {}

class User {
    @Inject        IApple apple;        // -> Apple1
    @Inject @Black IApple blackApple;   // -> Apple2
    @Inject @Red   IApple redApple;     // -> Error: not defined
}

Я хочу, чтобы, если компонент с определенным квалификатором не был определен, я бы хотел указать его по умолчанию, поэтому в приведенном выше примере redApple будет добавлен экземпляр Apple1.

Возможно ли это? Или я могу реализовать определенную стратегию сопоставления квалификаторов для Spring DI?

** РЕДАКТИРОВАТЬ **

Я знаю, что подкласс будет работать, но это пример для описания вопроса, поэтому подкласс здесь не применим.

1 Ответ

4 голосов
/ 16 марта 2011

Если вы попытаетесь ввести что-то с квалификацией, для которой не существует боба, например: @Inject @Red IApple redApple;, вы получите: NoSuchBeanDefinitionException.

Это исключение возникает независимо от того, используете ли вы:

  • @ Inject
  • @ Resource
  • @ Autowire

Причина проста: сначала поиск Spring DI определяет всекандидаты autowire.

  • если есть ровно один, то он использует этого кандидата
  • , если кандидата нет, он вызывает NoSuchBeanDefinitionException
  • , если большево-первых, он пытается определить первичного кандидата из кандидатов.

@ См. org.springframework.beans.factory.support.DefaultListableBeanFactory # doResolveDependency

, строка 785..809 (3.0.4.RELEASE)

То, что вам нужно сделать, это поместить запасной (Apple) в набор конфет, но убедитесь, что он используется только при наличиидругого кандидата нет.Поскольку нет способа пометить боб как отступившего или менее важного, вам нужно пометить нормальный боб как более важный: @primary.

Таким образом, (проверенное) решение будет аннотировать

  • Черно-красное яблоко с @Black и @Red и с @ Primary.
  • стандартный запасной вариант Apple (Apple1) с @Red и @Black, но без @ Primary.

Пример:

@Component @Red @Black public class Apple1 implements IApple {} //fall back
@Component @Black @Primary public class Apple2 implements IApple {}

@Component public class AppleEater {
  @Inject @Black IApple blackApple; // -> Apple2
  @Inject @Red IApple redApple; // -> Apple1
}

Возможное улучшение: Если вам не нравится добавлять все аннотации (@Black, @Red, @AllOtherStangeColors) в ваш резервный компонент, выможет попытаться внедрить свой собственный AutowireCandiateResolver, чтобы он добавил резервный компонент во все списки кандидатов необходимого типа (Apple) @, см. справочную документацию: 3.9.4 CustomAutowireConfigurer

...