[英]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. 我想要一个
UsernameProvider
服务,它负责提取登录用户的用户名。 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. 我希望有一个
UsernameProvider
接口的默认实现,它从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()
. 但是,在依赖于库的服务中,我想使用基本身份验证,因此我创建了一个覆盖
getUsername()
的BasicAuthUsernameProvider
。
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
. 当有多个相同类型的autowire候选者(
DefaultUsernameProvider
中的DefaultUsernameProvider
和服务中的BasicAuthUsernameProvider
)时,我自然会收到错误,因此我必须将服务中的bean标记为@Primary
。 But I don't want to have the library clients specify a primary bean, but instead mark a default. 但我不希望库客户端指定主bean,而是标记默认值。
Adding @Order(value = Ordered.LOWEST_PRECEDENCE)
on the DefaultUsernameProvider
didn't work. 添加
@Order(value = Ordered.LOWEST_PRECEDENCE)
在DefaultUsernameProvider
没有工作。
Adding @ConditionalOnMissingBean
in a Configuration class in the library didn't work either. 在
@ConditionalOnMissingBean
中的Configuration类中添加@ConditionalOnMissingBean
也不起作用。
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. 编辑:结果,在
UsernameProvider
实现类上添加@Component
使得@ConditionalOnMissingBean
无用,因为Spring Boot试图将每个注释为Component的类自动装配,因此抛出“找到类型的多个bean”异常。
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
. 你没有发布
DefaultUsernameProvider
的代码,但我猜它注释为@Component
因此它是自动连线的候选者,与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
类,并在那里创建UsernameProvider
bean:
@Configuration
public class ProviderConfig {
@Bean
public UsernameProvider() {
return new BasicAuthUsernameProvider();
}
}
This bean will then be auto wired wherever its needed 然后,这个bean将在需要的任何地方自动连接
You can annotate the method that instantiates your bean with @ConditionalOnMissingBean
. 您可以使用
@ConditionalOnMissingBean
注释实例化bean的方法。 This would mean that the method will be used to instantiate your bean only if no other UserProvider
is declared as a bean. 这意味着只有在没有其他
UserProvider
被声明为bean时,该方法才会用于实例化bean。
In the example below you must not annotate the class DefaultUserProvider
as Component
, Service
or any other bean annotation. 在下面的示例中,您不能将类
DefaultUserProvider
注释为Component
, Service
或任何其他bean注释。
@Configuration
public class UserConfiguration {
@Bean
@ConditionalOnMissingBean
public UserProvider provideUser() {
return new DefaultUserProvider();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.