Spring Fallback 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
),则在将依赖项自动装配到MyService
时,该bean应该始终优先于MyDefaultService
.在这方面,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,
艾伦
推荐答案
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屋!