我有一个界面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");
}
}
现在我有一个侦听器类,它有这个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");
}
}
这对我来说似乎是一种魅力。无论我需要注入哪个实现类,我都只需从其相应的Condition
类返回true
,并从实现类的其余Condition
类返回false
。
然而,下一部分是我面临挑战的地方: 因此,从上面的解决方案中,我从相应Condition
类的matches
方法中硬编码了return true
或return false
。如果我需要基于另一个组件返回动态值怎么办。
假设我有一个 SpringComponent
类MyCustomConfig
它有一个成员customFlag
,如果这个成员设置为 true,我们需要注入 ImplementationA.class。 我尝试了以下方法(使类@Component并自动连接MyCustomConfig):
@Component
public class ConditionA implements Condition {
@Autowired
MyCustomConfig myCustomConfig;
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return myCustomConfig.getCustomFlag();
}
}
但是,这根本不起作用。 myCustomConfig 不是自动连线的,我收到一个空指针异常。
有人可以帮我解决这个问题吗?
我认为使用implements Condition
没有机会满足您的需求.
如果您检查文档以了解interface Condition
这是您提供给@Conditional
的类应该执行的操作,在您的情况下ConditionA
并ConditionB
它说:
条件必须遵循与 BeanFactoryPostProcessor,注意永远不要与bean交互 实例。对相互作用的条件进行更精细的控制 有了@Configuration豆,考虑实现 配置条件接口。
也许这个答案会为您提供一种解决方法,正如上面文档中提到的,如果您想干扰其他 bean,您应该实现自己的自定义 ConfigurationCondition。
只需检查此配置条件将运行的阶段是否在注册了所需的 bean 之后
我会使用配置类和@Bean
注册 bean,如下所示:
@Configuration
public class ImplementationConfig {
@Bean
public IInterface implementation(MyCustomConfig myCustomConfig) {
if (myCustomConfig.getCustomFlag()) {
return new ImplementationA();
} else {
return new ImplementationB();
}
}
}
您只需将 Spring 相关的注释都放在ImplementationA
和ImplementationB
:
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
类。
在此处 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.