Spring后备bean实现

问题描述 投票:0回答:2

我目前正在尝试为以下场景配置Spring Boot(使用Java AnnotationsComponentScan):

场景

  • 有一个界面
    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 并发出警告。

谢谢并亲切的问候,

艾伦

spring annotations spring-boot autowired
2个回答
9
投票

我建议编写一个

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。


0
投票

传统上,在 Spring 中,您可以使用 @Primary 注释来标记 bean,这样在发现多个自动装配候选者的情况下,它将优先于未用

@Primary
注释的常规 bean。

但是,在 Spring 6.2 中引入了新注释 - @Fallback

它本质上与

@Primary

相反。仅当没有带有 
@Primary
 注释的 Bean 并且没有常规 Bean 时,才会使用此类 Bean。

© www.soinside.com 2019 - 2024. All rights reserved.