[英]How to autowire a bean inside a Spring @Condition class
我有一个接口IInterface.java
如下所示:
public interface IInterface {
void printIt();
}
为此有两个实现类: ImplementationA.java
和ImplementationB.java
@Component
public class ImplementationA implements IInterface {
@Override
public void printIt() {
System.out.println("Inside ImplementationA");
}
}
@Component
public class ImplementationB implements IInterface {
@Override
public void printIt() {
System.out.println("Inside ImplementationB");
}
}
现在我有一个监听器 class,它有这个IInterface
作为成员:
@Component
@AllArgsConstructor
public class Listener {
IInterface iInterface;
public void doStuff(){
iInterface.printIt();
}
}
现在,我的要求是根据特定条件在Listener.java
的iInterface
成员中注入ImplementationA.java
或ImplementationB.java
。
经过一些研究,我开始使用@Conditional
注释。 我添加了两个类ConditionA.java
和ConditionB.java
:
public class ConditionA implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
public class ConditionB implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true;
}
}
而且我还更改了我的实现类如下(添加了Conditional
注释):
@Component
@Conditional(ConditionA.class)
public class ImplementationA implements IInterface {
@Override
public void printIt() {
System.out.println("Inside ImplementationA");
}
}
@Component
@Conditional(ConditionB.class)
public class ImplementationB implements IInterface {
@Override
public void printIt() {
System.out.println("Inside ImplementationA");
}
}
这对我来说似乎是一种魅力。 无论我需要注入哪种实现 class,我只需从其相应的Condition
class 返回true
,并从实现类的Condition
rest 的条件 class 返回false
然而,下一部分是我面临挑战的地方:因此,从上述解决方案中,我对相应Condition
class 的matches
方法的return true
或return false
进行了硬编码。 如果我需要基于另一个组件返回一个动态值怎么办。
假设我有一个 spring Component
class MyCustomConfig
,它有一个成员customFlag
,如果这个成员设置为 true,我们需要注入 ImplementationA.class。 我尝试了以下方法(制作了 class @Component 并自动连接了 MyCustomConfig):
@Component
public class ConditionA implements Condition {
@Autowired
MyCustomConfig myCustomConfig;
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return myCustomConfig.getCustomFlag();
}
}
然而,这根本行不通。 myCustomConfig 没有自动装配,我得到一个 null 指针异常。
有人可以帮我解决这个问题。
我认为使用implements Condition
没有机会满足您的需求。
如果您检查interface Condition
的文档,这是您提供给 @Conditional 的@Conditional
应该做的,在您的情况下ConditionA
和ConditionB
它说:
条件必须遵循与 BeanFactoryPostProcessor 相同的限制,并注意永远不要与 bean 实例交互。 要对与 @Configuration bean 交互的条件进行更细粒度的控制,请考虑实现 ConfigurationCondition 接口。
正如上面在文档中提到的那样,这个答案可能会为您提供一种解决方法,如果您想干扰其他 bean,您应该实现自己的自定义 ConfigurationCondition。
只需检查此 ConfigurationCondition 将运行的阶段将在您需要的 bean 注册之后
在此处查看此链接https://stackoverflow.com/a/70351394/7237884 。
文档说
Conditions must follow the same restrictions as BeanFactoryPostProcessor and take care to never interact with bean instances. For more fine-grained control of conditions that interact with @Configuration beans consider implementing the ConfigurationCondition interface.
我将使用配置 class 和@Bean
注册 bean,如下所示:
@Configuration
public class ImplementationConfig {
@Bean
public IInterface implementation(MyCustomConfig myCustomConfig) {
if (myCustomConfig.getCustomFlag()) {
return new ImplementationA();
} else {
return new ImplementationB();
}
}
}
您只需在ImplementationA
和ImplementationB
中删除与 Spring 相关的注释:
public class ImplementationA implements IInterface {
@Override
public void printIt() {
System.out.println("Inside ImplementationA");
}
}
public class ImplementationB implements IInterface {
@Override
public void printIt() {
System.out.println("Inside ImplementationA");
}
}
最后,您可以删除Condition
类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.