springfallbackbean实现

springfallbackbean实现,spring,annotations,spring-boot,autowired,Spring,Annotations,Spring Boot,Autowired,我目前正在尝试为以下场景配置Spring Boot(使用Java注释和组件扫描): 场景 有一个接口MyService 我想为MyService提供一个默认实现,我们称之为MyDefaultService 如果组件扫描未检测到MyService的其他实现,Spring应将MyDefaultService实例化为“回退” 如果存在不同的MyService实现,比如说MyCustomService,那么在将依赖项自动关联到MyService时,该bean应该始终优先于MyDefaultServic

我目前正在尝试为以下场景配置Spring Boot(使用Java注释组件扫描):

场景

  • 有一个接口
    MyService
  • 我想为
    MyService
    提供一个默认实现,我们称之为
    MyDefaultService
  • 如果组件扫描未检测到MyService的其他实现,Spring应将MyDefaultService实例化为“回退”
  • 如果存在不同的
    MyService
    实现,比如说
    MyCustomService
    ,那么在将依赖项自动关联到
    MyService
    时,该bean应该始终优先于
    MyDefaultService
    。在这方面,
    MyDefaultService
    应该是隐性的(与
    @Primary
    相反)
  • 理想情况下,无需在
    MyCustomService
    上添加额外的注释即可“覆盖”
    MyDefaultService
  • 理想情况下,不需要显式实现工厂或工厂方法
问题

问题是:为了实现这一点,我需要如何注释
MyDefaultService

到目前为止我试图解决的问题

  • @ConditionalOnMissingBean(MyService.class)
    注释
    MyDefaultService
    。没有工作,因为从未使用过
    MyDefaultService
    ,即使没有其他
    MyService
    的实现
  • 有一个名为
    @Primary
    的注释解决了这个问题。但是,它需要驻留在
    MyCustomService
    上,我尽量不使用额外的注释。本质上,我需要
    MyDefaultService
    上的
    @Primary
    的反向注释。然而,我找不到这样的注释
具体用例

我正在一个项目中开发一个服务层,另一个项目将在其上实现一个web UI层。UI项目依赖于服务层项目。但是,对于在服务层实现的某些功能,我需要知道哪个用户当前在web上下文中登录。因此,我必须在服务层项目中为它定义一个服务接口,以便它可以由UI项目实现。但是,为了在服务层项目中进行测试,我需要该接口的默认实现。此外,如果UI项目团队忘记实现此接口,应用程序不应该崩溃,而是实例化回退bean并发出警告

谢谢和亲切的问候


Alan

我建议编写一个实现来实现这一点。您的
FactoryBean
将扫描bean工厂,寻找实现
MyService
的bean,如果找到了,它将从
getObject
返回该bean。如果没有,那么它可以直接实例化
MyDefaultService
,并返回它。然后用
@Primary
注释工厂bean

所以像这样的片段(伪代码):

Spring将自动处理工厂bean(即,它将使
MyService
对象像正常情况一样作为注入bean提供)


这个解决方案不需要任何特殊的魔法,它的工作原理非常明显。您还可以处理错误的情况,例如声明多个
MyService
bean。

myservicecfactory
中的
ListableBeanFactory-beanFactory
为空。如何解决这个问题?
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();
}