Spring回退bean实现 [英] Spring fallback bean implementation
问题描述
我目前正在尝试为以下场景配置 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 itMyDefaultService
. - If the component scan detects no other implementation for
MyService
, Spring should instantiateMyDefaultService
as a "fallback". - If there is a different implementation of
MyService
present, let's sayMyCustomService
, then that bean should always take precedence overMyDefaultService
when autowiring a dependency toMyService
. 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 becauseMyDefaultService
is never used, even if there is no other implementation ofMyService
. - There is an annotation called
@Primary
that solves the problem. However, it needs to reside onMyCustomService
, a class that I try to keep free of additional annotations. Essentially, I need the inverse annotation of@Primary
onMyDefaultService
. 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屋!