我正在编码一个库和使用该库的服务。我想要一个UsernameProvider
服务,该服务负责提取已登录用户的用户名。我在库本身中使用了该服务:
class AuditService {
@Autowired
UsernameProvider usernameProvider;
void logChange() {
String username = usernameProvider.getUsername();
...
}
}
我想要一个UsernameProvider
接口的默认实现,该接口从JWT的主题声明中提取用户名。但是,在依赖于库的服务中,我想使用基本身份验证,因此,我将创建一个覆盖BasicAuthUsernameProvider
的{{1}}。
当有多个相同类型的自动装配候选对象(库中的getUsername()
和服务中的DefaultUsernameProvider
)时,我自然会出错,因此我必须在服务为BasicAuthUsernameProvider
。但是我不想让库客户端指定一个主bean,而是将其标记为默认值。
在@Primary
上添加@Order(value = Ordered.LOWEST_PRECEDENCE)
无效。
在库的Configuration类中添加DefaultUsernameProvider
也不起作用。
编辑:结果是,在@ConditionalOnMissingBean
实现类上添加@Component
会使UsernameProvider
无效,因为Spring Boot尝试自动装配每个注释为Component的类,因此抛出“找到了多个类型的豆” 异常。
答案 0 :(得分:1)
您尚未发布DefaultUsernameProvider
的代码,但我想它的注释为@Component
,因此它是自动接线的候选对象,与BasicAuthUsernameProvider
相同。如果要控制使用其中的哪个,而不是将它们都标记为组件,则添加一个@Configuration
类,然后在其中创建UsernameProvider
bean:
@Configuration
public class ProviderConfig {
@Bean
public UsernameProvider() {
return new BasicAuthUsernameProvider();
}
}
此bean将在需要的地方自动接线
答案 1 :(得分:1)
您可以注释使用@ConditionalOnMissingBean
实例化bean的方法。这意味着仅当没有其他UserProvider
被声明为bean时,该方法才会用于实例化bean。
在下面的示例中,您不得将类DefaultUserProvider
注释为Component
,Service
或任何其他bean注释。
@Configuration
public class UserConfiguration {
@Bean
@ConditionalOnMissingBean
public UserProvider provideUser() {
return new DefaultUserProvider();
}
}