如何在春季@Condition类中自动连接 bean



我有一个界面IInterface.java如下所示:

public interface IInterface {
void printIt();
}

为此有两个实现类:ImplementationA.javaImplementationB.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.javaiInterface成员中注入ImplementationA.javaImplementationB.java

经过一番研究,我开始使用@Conditional注释。 我添加了两个类ConditionA.javaConditionB.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 truereturn false。如果我需要基于另一个组件返回动态值怎么办。

假设我有一个 SpringComponentMyCustomConfig它有一个成员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的类应该执行的操作,在您的情况下ConditionAConditionB它说:

条件必须遵循与 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 相关的注释都放在ImplementationAImplementationB

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.

最新更新