如何将一个bean注入Spring Condition类?

时间:2018-08-29 07:31:46

标签: java spring spring-boot annotations spring-4

我正在定义要检查的条件,以便稍后动态加载服务接口的两个实现之一。

@Component
public class IsPolicyEnabled implements Condition {

    @Autowired
    private MyProperties props;

    @Override
    public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
        return props.isPolicyEnabled();
    }

}

还有

@Component
public class MyProperties {...}

@Service
@Conditional(IsPolicyEnabled.class)
public class ServiceA implements Service {...}

但是,我遇到了运行时错误。

java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: java.lang.NullPointerException
at com.xyz.utils.IsPolicyEnabled.matches(IsPolicyEnabled.java:9)
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108)
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:88)
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:71)
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.isConditionMatch(ClassPathScanningCandidateComponentProvider.java:515)

基本上,它无法初始化已在条件实现中自动连线的props对象。不允许吗?

由于条件评估取决于该依赖关系提供的值,我该如何在条件实现内部自动关联另一个依赖关系?

2 个答案:

答案 0 :(得分:4)

  

在要注册豆定义之前立即检查条件

     

Condition, Spring Framework 5.0.8.RELEASE API documentation

您不能将bean注入Condition实例中,因为上下文中还没有bean定义 1

此外,您不应该使用Condition类中的bean:

  

条件必须遵循与BeanFactoryPostProcessor相同的限制,并且注意切勿与bean实例进行交互

     

Condition, Spring Framework 5.0.8.RELEASE API documentation

您应该重新考虑设计,因为

  

[...]我的状态评估取决于该依赖项提供的值。

表示不太正确。

1 确切地说,Spring已经为自己的需要注册了一些bean。

答案 1 :(得分:0)

有两个问题:

1)条件类没有注入

解决方案是从ConditionContext中检索bean:

@Component
public class IsPolicyEnabled implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        MyProperties props = context.getBeanFactory().getBean(MyProperties.class);

        return props.isPolicyEnabled();
    }
}

2)条件初始化发生得很早

尝试从ConditionContext检索bean失败NoSuchBeanDefinitionException: No qualifying bean of type ...,因为条件检查发生在Spring生命周期的早期。

一种解决方案是具有两个Spring上下文:

  • 仅定义MyProperties
  • 的parentContext
  • 定义了应用程序其余部分并以parentContext作为其父对象的childContext

因此,在调用条件时,已经在父上下文中创建了MyProperties

ApplicationContext parentContext = new AnnotationConfigApplicationContext(MyProperties.class);
ApplicationContext childContext = new AnnotationConfigApplicationContext();
childContext.setParent(parent);
childContext.register(ApplicationConfiguration.class);
childContext.refresh();

Service service = childContext.getBean(Service.class);
// do something with service