Spring Fallback Bean的实现 [英] Spring fallback bean implementation

查看:131
本文介绍了Spring Fallback 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),则在将依赖项自动装配到MyService时,该bean应该始终优先于MyDefaultService.在这方面,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@Primary inverse 批注.但是,我找不到这样的注释.
  • 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,

艾伦

推荐答案

我建议编写

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 Fallback Bean的实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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