【问题标题】:Produce Optional Beans in CDI在 CDI 中生成可选 Bean
【发布时间】:2019-12-05 08:47:12
【问题描述】:

我想在方法上使用 @Produces 注释创建一个 CDI 工厂,以便在外部服务中查找命名的东西并返回(生成)外部服务中该东西的代理以注入其他 bean .从用例的角度来看,通常所有这些依赖项都是必需的;但是有时会发生请求的东西在远程服务中不存在并且应用程序可以对此作出反应。

基本上结构是这样的:

@Singleton public class SomeBean {
  @Inject @MyName("required") private Something requiredSomething;
  @Inject @MyName("optional") private Instance<Something> optionalSomething;

  @PostConstruct void init() {
    if (optionalSomething.isUnSatisfied()) {
      // act without optional Something in external service
    } else {
      optionalSomething.get().doWhatIWant(NOW);
    }
  }
}

@ApplicationScoped
public class SomethingFactory {
  @Inject private RemoteSomethingService remoteService;

  @Produces
  @MyName(value = "")
  public Something createRemoteSomething(InjectionPoint injectionPoint) {
    MyName name = injectionPoint.getAnnotated().getAnnotation(MyName.class);
    Something some = remoteService.lookup(name.value()); // throws an exception if lookup fails
    return some;
  }
}

这适用于需要在使用某些东西的一侧进行注入的情况:成功的查找注入查找的 Something 实例,而不成功的查找会破坏 bean 引导。然而,在一个不存在的东西的可选注入的情况下,它要么中断,因为Instance.isUnSatisfied() 返回false。如果我让createRemoteSomething() 抛出异常,则在调用optionalSomething.get() 期间会引发此异常;如果我返回 null,同样的调用会导致 NPE。

如何使用 CDI 原语实现这一点?谢谢。

【问题讨论】:

    标签: java jakarta-ee cdi


    【解决方案1】:

    您的生产者方法很好(我假设它的返回类型应该是Something)。您正在@Dependent 范围内生成Something(默认值)。

    @Dependent 范围内的内容可能是null。一般来说,没有别的可能。 (CDI 中有一些从远古时代就可以产生null 对象的剩余位,但它们是过去时代的残余。)

    所以在你的情况下,当你不能生产你想要的东西时,只需从你的生产者方法中返回null,但这不是错误条件(否则显然会抛出某种异常)。

    那么,在消费方面,你就快到了。

    Instance#isUnsatisfied() 仅在没有生产者方法(或其他类型的 bean)可以“制造”所要求的东西时才返回 true。在你的情况下,一个生产者方法可以“制造”被要求的东西,所以isUnsatisfied()返回false,这是正确的。

    你应该做的就是改变这个:

    optionalSomething.get().doWhatIWant(NOW);
    

    …到:

    final Something something = optionalSomething.get();
    if (something == null) {
      // no such Something, but an expected case
    } else {
      something.doWhatIWant(NOW);
    }
    

    同样,这仅在 Something 位于 @Dependent 范围内(而不是 @ApplicationScoped 范围内)时才有效,而您的情况确实如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-20
      • 2022-10-12
      • 1970-01-01
      • 2013-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多