Spring fallback bean实现

时间:2015-01-01 23:40:27

标签: spring annotations spring-boot autowired

我目前正在尝试针对以下情况配置 Spring Boot (使用 Java注释 ComponentScan ):

方案

  • 有一个界面MyService
  • 我想为MyService提供一个默认实现,我们称之为MyDefaultService
  • 如果组件扫描未检测到MyService的其他实现,则Spring应将MyDefaultService实例化为“后备”。
  • 如果存在MyService的不同实现,让我们说MyCustomService,那么当自动装配依赖关系时,该bean应始终优先于MyDefaultService MyService。在这方面,MyDefaultService应该隐性(而不是@Primary)。
  • 理想情况下,MyCustomService上不需要额外的注释,以使其“覆盖”MyDefaultService
  • 理想情况下,不需要明确实施的工厂或工厂方法。

问题

问题是:为了达到这个目的,我如何需要注释MyDefaultService类?

到目前为止我尝试解决问题

  • 使用MyDefaultService注释@ConditionalOnMissingBean(MyService.class)。因为MyDefaultService从未使用过,所以没有用,即使没有MyService的其他实现。
  • 有一个名为@Primary的注释可以解决问题。但是,它需要驻留在MyCustomService上,这是一个我试图保留其他注释的类。基本上,我需要@PrimaryMyDefaultService注释。但是,我找不到这样的注释。

具体用例

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

谢谢&亲切的问候,

艾伦

1 个答案:

答案 0 :(得分:3)

我建议编写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 bean。