当前位置: 首页 > 知识库问答 >
问题:

CDI范围和生产者

郭弘盛
2023-03-14

有人能解释一下CDI范围注释在生产者中的作用吗?他们似乎什么也做不了。

@Produces
public Thing thingMaker() {
    System.out.println("Making thingmaker");
    return new ThingBean("thingMaker");
}

@Produces
@RequestScoped
public Thing thingMakerReq() {
    System.out.println("Making thingmakerReq");
    return new ThingBean("thingMakerReq");
}

这些,自然地,在启动时给出了这个(省略的)错误。

WELD-001409:类型的依赖关系不明确。可能的依赖关系:

  • 带有限定符[@Any@Default]的生产者方法[Thing]声明为[[BackedAnnotatedMethod]@生成公共pkg。测验东西制作人。thingMaker(),

因此,尽管“RequestScoped”是producer方法的一部分,但它们不是限定符。

所以我不确定他们在制作方法上的角色是什么。

共有1个答案

曾洲
2023-03-14

生产者方法上的CDI范围注释定义了所产生bean的范围;因此:

@Produces // produces Thing in the default scope, i.e. @Dependent
public Thing thingMaker() {
    System.out.println("Making thingmaker");
    return new ThingBean("thingMaker");
}

@Produces // produces Thing in request scope
@RequestScoped
public Thing thingMakerReq() {
    System.out.println("Making thingmakerReq");
    return new ThingBean("thingMakerReq");
}

如果只有这两种方法,它们将能够和平共处。当你想注入一个Thing时,问题就出现了,如:

    @Inject
    private Thing thing;

CDI搜索其名称空间并找到多个可以满足该注入点的bean;由于不知道该怎么做,它失败了(在特定情况下,如果WELD是CDI实施,则使用WELD-001409)。例如,以下内容完全合法:

    @Inject
    private Instance<Thing> things;

实例可以为您提供满足注入点的bean集合,您可以选择其中任何一个来使用。

现在,限定符是另一回事,与CDI如何找到满足注入点的bean有关。

首先,消除误解:范围注释不是限定符。您可以注意到,在CDI的消息中,“将限定符[@Any@Default]声明为[[…@RequestScoped…]”。这也意味着您不能从注入点的特定范围请求bean。包含注入点的bean的范围在选择注入bean时也不起任何作用。作用域是bean的一个实现细节:假设您有一个@ApplicationScopedbean,然后在某个时候您意识到它需要请求级别的信息来实现某些功能。你可以改变它的范围,而使用它的bean不应该在意,它们将继续工作而不会改变。

限定符是在类型不够时消除依赖关系歧义的一种方法,比如在您的案例中。一个常见的例子是当有许多配置属性时,用字符串表示。比如说一个DB用户名和密码,两种类型都是String:(警告:简单的例子是,带有绑定属性的限定符更合适,请参见例如microfile config)

    @Inject
    @DbUsername // this is the qualifier
    private String dbUsername;

    @Inject
    @DbPassword // this is the qualifier
    private String dbPassword;
 类似资料:
  • 本文解释了可以将RequestScoped Bean注入ApplicationScoped Bean中,并且客户机代理将在请求期间指向正确的实例:在CDI中,较短范围的Bean实例注入较大范围的Bean实例中-它是如何工作的? 当使用一个单独的生产者类进行额外处理并生成RequestScoped bean时,这是如何工作的?在部署到应用服务器时,由于不明确的依赖关系,我得到一个Deployment

  • tl;dr注入servlet的CDIBean如何可能也在适当的范围内? 在oracle官方教程和一些书籍中,我们可以看到一些简单的示例,展示如何将CDIBean注入servlet。这非常简单,因为我们只需要使用@Inject注释并在bean中启用bean发现。xml。我不明白的是,注入servlet的@RequestScoped或@SessionScoped bean的作用域是否正确。servle

  • 问题内容: 我正在尝试生成一个随机双精度值,但不包括它的下限和上限(下限,上限)。我已经看到了很多有关生成数字的问题,包括从数字的下限到上限,但不包括数字的上限(下限,上限),但是由于没有解决此问题,因此他们没有回答我的问题。 我已经为这个问题提出了两个“解决方案”,但都不是很满意。 第一个“解决方案” 尽管这几乎每次都会在第一次尝试时给出有效的结果,但它似乎不一致且笨拙,并且如果rng经常返回0

  • NutIoc 实现了 Ioc2 接口,它继承自 Ioc 接口,并多出了两个方法。 一个允许你自行添加自定义的值类型,另一个是允许你在获取对象时,链入自己的上下文环境 请阅读 org.nutz.ioc.IocContext 的接口文档, 你可以根据需要实现这个上下文接口 这个设计有什么用? 比如,在一个 Web 应用中,你希望在会话中保存一个数据源,你不希望这个数据源保存在 Application

  • 在用户登录时续订HTTP会话是常见的最佳做法。这将强制使用新的会话ID,从而避免会话固定漏洞。 当涉及@SessionScoped bean时,是否有使用CDI实现此功能的首选模式?困难在于,通过使当前HTTP会话无效,您将在下一个请求中获得不同的会话范围bean,但直到下一个请求。 例如,假设一个用于存储用户登录信息的会话bean: 和另一个用于管理登录的bean: 对于托管Bean,这将检索一

  • 问题内容: 因此,我在此代码位中的目标是随机掷两个骰子,众所周知,您的普通骰子只有6个面,因此我导入了Foundation以访问arc4random_uniform(UInt32)。我尝试使用(1..7)的范围来避免随机获得0,但是返回了一个我不太喜欢的错误。我试图这样做: 但是那又回来了 找不到接受提供的参数的’init’的重载 我希望这是足够的信息,可以为您提供帮助,帮助您:) 请注意,我只是