我目前正在尝试为以下场景配置Spring Boot(使用Java Annotations和ComponentScan):
场景
MyService
。MyService
提供默认实现,我们称之为 MyDefaultService
。MyService
的其他实现,Spring 应将 MyDefaultService
实例化为“后备”。MyService
的不同实现,比如说 MyCustomService
,那么当自动装配对 MyDefaultService
的依赖时,该 bean 应该 always优先于
MyService
。在这方面,MyDefaultService
应该是隐性(而不是@Primary
)。MyCustomService
上添加额外注释即可“覆盖”MyDefaultService
。问题
问题是:我需要如何注释
MyDefaultService
类才能实现此目的?
到目前为止我尝试解决问题的方法
MyDefaultService
注释 @ConditionalOnMissingBean(MyService.class)
。不起作用,因为 MyDefaultService
从未使用过,即使没有其他 MyService
的实现。@Primary
的注释可以解决这个问题。然而,它需要驻留在 MyCustomService
上,我试图让这个类免于附加注释。本质上,我需要 @Primary
上的 MyDefaultService
的 inverse注释。但是我找不到这样的注释。
具体用例
我正在一个项目中开发一个服务层,另一个项目将在其之上实现一个 Web UI 层。 UI 项目依赖于服务层项目。但是,对于在服务层实现的某些功能,我需要知道哪个用户当前在 Web 上下文中登录。所以我必须在服务层项目中为其定义一个服务接口,以便它可以由UI项目实现。但是,为了在服务层项目中进行测试,我需要该接口的默认实现。此外,如果 UI 项目团队忘记实现此接口,应用程序不应崩溃,而应实例化后备 bean 并发出警告。
谢谢并亲切的问候,
艾伦
FactoryBean
的实现来执行此操作。您的 FactoryBean
将扫描 Bean 工厂,查找实现 MyService
的 Bean,如果找到,则从 getObject
返回该 Bean。如果没有,那么它可以直接实例化 MyDefaultService
并返回它。然后你的工厂 bean 就会被注释为 @Primary
。
像这样的片段(伪代码):
public class MyServiceFactory implements FactoryBean<MyService> {
ListableBeanFactory beanFactory;
public MyService getObject() {
Map beans = beanFactory.getBeansOfType(MyService.class)
if (beans.isEmpty())
return new MyDefaultService(); // plus args, obviously
else
return get_some_bean_from_the_map
}
}
然后
@Primary
@Bean
public MyServiceFactory MyServiceFactory() {
return new MyServiceFactory();
}
Spring 将自动处理工厂 bean(即,它将使
MyService
对象可以像平常一样作为 bean 进行注入。
这个解决方案不需要任何特殊的魔法,而且它的工作原理相当明显。您还可以处理错误的情况,例如声明多个
MyService
beans。
传统上,在 Spring 中,您可以使用 @Primary 注释来标记 bean,这样在发现多个自动装配候选者的情况下,它将优先于未用
@Primary
注释的常规 bean。
但是,在 Spring 6.2 中引入了新注释 - @Fallback
。它本质上与
@Primary
相反。仅当没有带有
@Primary
注释的 Bean 并且没有常规 Bean 时,才会使用此类 Bean。