Как указать bean-компонент по умолчанию для автопроводки в Spring? - PullRequest
0 голосов
/ 04 декабря 2018

Я кодирую библиотеку и сервис, использующий эту библиотеку.Я хочу иметь сервис UsernameProvider, который позаботится о извлечении имени пользователя вошедшего в систему пользователя.Я использую службу в самой библиотеке:

class AuditService {
  @Autowired
  UsernameProvider usernameProvider;

  void logChange() {
    String username = usernameProvider.getUsername();
    ...
  }
}

Я хочу иметь реализацию по умолчанию интерфейса UsernameProvider, которая извлекает имя пользователя из субъектного утверждения JWT.Однако в сервисе, который зависит от библиотеки, я хочу использовать обычную аутентификацию, поэтому я бы создал BasicAuthUsernameProvider, который переопределяет getUsername().

Естественно, я получаю сообщение об ошибке, когда есть несколько кандидатов на автоматическое подключение одного и того же типа (DefaultUsernameProvider в библиотеке и BasicAuthUsernameProvider в службе), поэтому мне придется пометить компонент в службекак @Primary.Но я не хочу, чтобы клиенты библиотеки указывали основной компонент, а вместо этого отмечали значение по умолчанию.

Добавление @Order(value = Ordered.LOWEST_PRECEDENCE) в DefaultUsernameProvider не работало.

Добавление @ConditionalOnMissingBean в классе конфигурации в библиотеке тоже не работал.

EDIT: Оказывается, добавление @Component в UsernameProvider классы реализации делает @ConditionalOnMissingBean бесполезным, так какSpring Boot пытается автоматически связать каждый класс, аннотированный как Компонент, поэтому выдает исключение «Несколько бинов типа найдено» .

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Вы можете аннотировать метод, который создает экземпляр вашего компонента с помощью @ConditionalOnMissingBean.Это будет означать, что метод будет использоваться для создания экземпляра вашего компонента только в том случае, если никакой другой UserProvider не объявлен как компонент.

В следующем примере вы не должны аннотировать класс DefaultUserProvider как Component,Service или любая другая аннотация компонента.

@Configuration
public class UserConfiguration {

  @Bean
  @ConditionalOnMissingBean
  public UserProvider provideUser() {

    return new DefaultUserProvider();
  }
}
0 голосов
/ 04 декабря 2018

Вы не опубликовали код для DefaultUsernameProvider, но я предполагаю, что он аннотирован как @Component, поэтому он является кандидатом на автоматическое подключение и то же самое с BasicAuthUsernameProvider.Если вы хотите контролировать, какой из них используется, вместо того, чтобы отмечать их как компоненты, добавьте класс @Configuration и создайте свой компонент UsernameProvider:

@Configuration
public class ProviderConfig {
    @Bean
    public UsernameProvider() {
         return new BasicAuthUsernameProvider();
    }
}

Этот компонент будет автоматическипроводной везде, где это необходимо

...