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.
You've not posted the code for DefaultUsernameProvider
but I guess its annotated as a @Component
so it is a candidate for auto wiring, and the same with the BasicAuthUsernameProvider
. If you want to control which of these is used, rather than marking them both as components, add a @Configuration
class, and create your UsernameProvider
bean there:
@Configuration
public class ProviderConfig {
@Bean
public UsernameProvider() {
return new BasicAuthUsernameProvider();
}
}
This bean will then be auto wired wherever its needed
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();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.