Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specify a default bean for autowiring in Spring?

I am coding both a library and service consuming this library. I want to have a UsernameProvider service, which takes care of extracting the username of the logged in user. I consume the service in the library itself:

class AuditService {
  @Autowired
  UsernameProvider usernameProvider;

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

I want to have a default implementation of the UsernameProvider interface that extracts the username from the subject claim of a JWT. However, in the service that depends on the library I want to use Basic authentication, therefore I'd create a BasicAuthUsernameProvider that overrides getUsername().

I naturally get an error when there are multiple autowire candidates of the same type (DefaultUsernameProvider in the library, and BasicAuthUsernameProvider in the service), so I'd have to mark the bean in the service as @Primary. But I don't want to have the library clients specify a primary bean, but instead mark a default.

Adding @Order(value = Ordered.LOWEST_PRECEDENCE) on the DefaultUsernameProvider didn't work.

Adding @ConditionalOnMissingBean in a Configuration class in the library didn't work either.

EDIT: Turns out, adding @Component on the UsernameProvider implementation classes renders @ConditionalOnMissingBean useless, as Spring Boot tries to autowire every class annotated as a Component, therefore throwing the "Multiple beans of type found" exception.

like image 234
Boyan Kushlev Avatar asked Oct 27 '22 23:10

Boyan Kushlev


1 Answers

You can annotate the method that instantiates your bean with @ConditionalOnMissingBean. This would mean that the method will be used to instantiate your bean only if no other UserProvider is declared as a bean.

In the example below you must not annotate the class DefaultUserProvider as Component, Service or any other bean annotation.

@Configuration
public class UserConfiguration {

  @Bean
  @ConditionalOnMissingBean
  public UserProvider provideUser() {

    return new DefaultUserProvider();
  }
}
like image 192
NewestStackOverflowUser Avatar answered Nov 15 '22 05:11

NewestStackOverflowUser