如何在 Spring 中为自动装配指定默认 bean?
How to specify a default bean for autowiring in Spring?
我正在编写库和使用该库的服务。我想要一个 UsernameProvider
服务,它负责提取登录用户的用户名。我使用图书馆本身的服务:
class AuditService {
@Autowired
UsernameProvider usernameProvider;
void logChange() {
String username = usernameProvider.getUsername();
...
}
}
我想要 UsernameProvider
接口的默认实现,该接口从 JWT 的主题声明中提取用户名。但是,在依赖库的服务中,我想使用基本身份验证,因此我会创建一个覆盖 getUsername()
的 BasicAuthUsernameProvider
。
当有多个相同类型的自动装配候选项(库中的DefaultUsernameProvider
,服务中的BasicAuthUsernameProvider
)时,我自然会出错,所以我必须标记bean在服务中为 @Primary
。但是我不想让库客户端指定主 bean,而是标记为默认值。
在 DefaultUsernameProvider
上添加 @Order(value = Ordered.LOWEST_PRECEDENCE)
无效。
在库中的配置 class 中添加 @ConditionalOnMissingBean
也不起作用。
编辑: 事实证明,在 UsernameProvider
实现上添加 @Component
classes 使 @ConditionalOnMissingBean
无用,因为 Spring Boot 尝试自动装配每个 class 注释为组件,因此抛出 "Multiple beans of type found" 异常。
您没有发布 DefaultUsernameProvider
的代码,但我猜它被注释为 @Component
,因此它是自动接线的候选者,BasicAuthUsernameProvider
也是如此。如果你想控制使用其中的哪一个,而不是将它们都标记为组件,添加一个 @Configuration
class,并在那里创建你的 UsernameProvider
bean:
@Configuration
public class ProviderConfig {
@Bean
public UsernameProvider() {
return new BasicAuthUsernameProvider();
}
}
然后这个 bean 将在需要的地方自动连接
您可以使用 @ConditionalOnMissingBean
注释实例化 bean 的方法。这意味着只有当没有其他 UserProvider
被声明为 bean 时,该方法才会用于实例化您的 bean。
在下面的示例中,您不得将 class DefaultUserProvider
注释为 Component
、Service
或任何其他 bean 注释。
@Configuration
public class UserConfiguration {
@Bean
@ConditionalOnMissingBean
public UserProvider provideUser() {
return new DefaultUserProvider();
}
}
我正在编写库和使用该库的服务。我想要一个 UsernameProvider
服务,它负责提取登录用户的用户名。我使用图书馆本身的服务:
class AuditService {
@Autowired
UsernameProvider usernameProvider;
void logChange() {
String username = usernameProvider.getUsername();
...
}
}
我想要 UsernameProvider
接口的默认实现,该接口从 JWT 的主题声明中提取用户名。但是,在依赖库的服务中,我想使用基本身份验证,因此我会创建一个覆盖 getUsername()
的 BasicAuthUsernameProvider
。
当有多个相同类型的自动装配候选项(库中的DefaultUsernameProvider
,服务中的BasicAuthUsernameProvider
)时,我自然会出错,所以我必须标记bean在服务中为 @Primary
。但是我不想让库客户端指定主 bean,而是标记为默认值。
在 DefaultUsernameProvider
上添加 @Order(value = Ordered.LOWEST_PRECEDENCE)
无效。
在库中的配置 class 中添加 @ConditionalOnMissingBean
也不起作用。
编辑: 事实证明,在 UsernameProvider
实现上添加 @Component
classes 使 @ConditionalOnMissingBean
无用,因为 Spring Boot 尝试自动装配每个 class 注释为组件,因此抛出 "Multiple beans of type found" 异常。
您没有发布 DefaultUsernameProvider
的代码,但我猜它被注释为 @Component
,因此它是自动接线的候选者,BasicAuthUsernameProvider
也是如此。如果你想控制使用其中的哪一个,而不是将它们都标记为组件,添加一个 @Configuration
class,并在那里创建你的 UsernameProvider
bean:
@Configuration
public class ProviderConfig {
@Bean
public UsernameProvider() {
return new BasicAuthUsernameProvider();
}
}
然后这个 bean 将在需要的地方自动连接
您可以使用 @ConditionalOnMissingBean
注释实例化 bean 的方法。这意味着只有当没有其他 UserProvider
被声明为 bean 时,该方法才会用于实例化您的 bean。
在下面的示例中,您不得将 class DefaultUserProvider
注释为 Component
、Service
或任何其他 bean 注释。
@Configuration
public class UserConfiguration {
@Bean
@ConditionalOnMissingBean
public UserProvider provideUser() {
return new DefaultUserProvider();
}
}