Spring回退bean实现 [英] Spring fallback bean implementation

查看:22
本文介绍了Spring回退bean实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm currently trying to configure Spring Boot (using Java Annotations and ComponentScan) for the following scenario:

场景

  • 有一个接口 MyService.
  • 我想为 MyService 提供一个默认实现,我们称之为 MyDefaultService.
  • 如果组件扫描没有检测到 MyService 的其他实现,Spring 应该将 MyDefaultService 实例化为后备".
  • 如果存在 MyService 的不同实现,比如 MyCustomService,那么该 bean 应该总是优先于 MyDefaultService 将依赖项自动装配到 MyService 时.在这方面,MyDefaultService 应该是隐性(而不是 @Primary).
  • 理想情况下,MyCustomService 上不需要额外的注释来覆盖"MyDefaultService.
  • 理想情况下,不需要明确实现的工厂或工厂方法.
  • There's an interface MyService.
  • I want to provide a default implementation for MyService, let's call it MyDefaultService.
  • If the component scan detects no other implementation for MyService, Spring should instantiate MyDefaultService as a "fallback".
  • If there is a different implementation of MyService present, let's say MyCustomService, then that bean should always take precedence over MyDefaultService when autowiring a dependency to MyService. In that regard, MyDefaultService should be recessive (as opposed to @Primary).
  • Ideally, there should not need to be an additional annotation on MyCustomService to have it "override" MyDefaultService.
  • Ideally, no explicitly implemented factories or factory methods should be required.

问题

问题是:我需要如何注释 MyDefaultService 类才能实现这一点?

The question is: how do I need to annotate the MyDefaultService class in order to achieve this?

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

  • 使用 @ConditionalOnMissingBean(MyService.class) 注释 MyDefaultService.没有工作,因为 MyDefaultService 从未被使用过,即使没有其他的 MyService 实现.
  • 有一个名为 @Primary 的注释可以解决这个问题.但是,它需要驻留在 MyCustomService 上,我尽量避免添加额外的注释.本质上,我需要 MyDefaultService 上的 @Primaryinverse 注释.但是,我找不到这样的注释.
  • Annotating MyDefaultService with @ConditionalOnMissingBean(MyService.class). Didn't work because MyDefaultService is never used, even if there is no other implementation of MyService.
  • There is an annotation called @Primarythat solves the problem. However, it needs to reside on MyCustomService, a class that I try to keep free of additional annotations. Essentially, I need the inverse annotation of @Primary on MyDefaultService. However, I couldn't find such an annotation.

具体用例

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

I am developing a service layer in one project, and a different project will implement a web UI layer on top of it. The UI project has a dependency to the service layer project. However, for certain functionalities implemented at the service layer, I need to know which user is currently logged in at the web context. So I have to define a service interface for that in the service layer project, such that it can be implemented by the UI project. However, for testing purposes in the service-layer project, I need a default implementation of that interface. Also, in case that the UI project team forgets to implement this interface, the app should not crash, but instead instantiate the fallback bean and issue a warning.

谢谢&亲切的问候,

Thanks & kind regards,

艾伦

推荐答案

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

I suggest writing an implementation of FactoryBean to do this. Your FactoryBean would scan the bean factory looking for beans that implement MyService, and if it finds one it returns that bean from getObject. If it doesn't, then it can instantiate MyDefaultService directly and return that. Your factory bean then gets annotated with @Primary.

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

So pieces like this (pseudo-code):

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 可用.

Spring will automatically handle the factory bean (i.e. it will make the MyService object available as a bean for injection like normal.

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

This solution doesn't require any special magic, and it's fairly obvious how it works. You can also handle errant cases such as multiple MyService beans being declared.

这篇关于Spring回退bean实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆