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

继承权中类型的CDI注入

仲孙默
2023-03-14

我有一个超类型(CaseDTO),其中有几个子类型(GroupCaseDTO,IPCaseDTO),我想注入。开发环境是JDev 12c。

以下是两个注射点:

>

@将@CaseContext private CaseDTO muwCase注入;

注入特定子类型(此注入点仅适用于一个子类型):

@将@CaseContext private GroupCaseDTO muwCase注入;

为了获得这些值,我尝试设置了许多生产者方法:

// supertype
@Produces @CaseContext
public CaseDTO getContextCase()  {
    return JSFUtils.getFromPageFlowScope("case", CaseDTO.class);
}

// subtype 1
@Produces @CaseContext
public IPCaseDTO getContextIpCase()  {
    return JSFUtils.getFromPageFlowScope("case", IPCaseDTO.class);
}

// subtype 2
@Produces @CaseContext
public GroupCaseDTO getContextGroupCase()  {
    return JSFUtils.getFromPageFlowScope("case", GroupCaseDTO.class);
}

问题是,如果我只包含超类型生产者方法,那么子类型注入点不起作用:

:org.jboss.weld.exceptions.DeploymentException:WELD-001408: Unsatisfied dependencies for type GroupCaseDTO with qualifiers @CaseContext
at injection point [BackedAnnotatedField] @Inject @CaseContext private ca.bluecross.ab.muw.view.controller.decision.ManageGrpDecisionController.muwCase
at ca.bluecross.ab.muw.view.controller.decision.ManageGrpDecisionController.muwCase(ManageGrpDecisionController.java:0)
WELD-001475: The following beans match by type, but none have matching qualifiers:
- Managed Bean [class ca.bluecross.ab.muw.model.type.dto.grp.GroupCaseDTO] with qualifiers [@Any @Default]

但是如果我包括所有三种生产者方法,我就会在超类型注入点得到这个异常

:org.jboss.weld.exceptions.DeploymentException:WELD-001409: Ambiguous dependencies for type CaseDTO with qualifiers @CaseContext
at injection point [BackedAnnotatedField] @Inject @CaseContext private ca.bluecross.ab.muw.view.controller.UploadAssociatedDocumentController.muwCase
at ca.bluecross.ab.muw.view.controller.UploadAssociatedDocumentController.muwCase(UploadAssociatedDocumentController.java:0)
Possible dependencies: 
  - Producer Method [CaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextCase()],
  - Producer Method [GroupCaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextGroupCase()],
  - Producer Method [IPCaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextIpCase()]

只有两个子类型生成器方法也不起作用:

:org.jboss.weld.exceptions.DeploymentException:WELD-001409: Ambiguous dependencies for type CaseDTO with qualifiers @CaseContext
  at injection point [BackedAnnotatedField] @Inject @CaseContext private ca.bluecross.ab.muw.view.controller.UploadAssociatedDocumentController.muwCase
  at ca.bluecross.ab.muw.view.controller.UploadAssociatedDocumentController.muwCase(UploadAssociatedDocumentController.java:0)
  Possible dependencies: 
  - Producer Method [GroupCaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextGroupCase()],
  - Producer Method [IPCaseDTO] with qualifiers [@CaseContext @Any] declared as [[BackedAnnotatedMethod] @Produces @CaseContext public ca.bluecross.ab.muw.view.util.DataContextHelper.getContextIpCase()]

我想我可以通过为我需要的每个子类型使用限定符注释来解决这个问题,但这似乎太过分了。如果没有大量的限定符注释,就没有办法让注入工作吗?

事实上,我想要的是:一个生产者方法一个限定符注释,它允许我注入上下文大小写,而不管它是什么子类型。同样,我认为CDI不可能做到这一点,因为它(太)强类型。

共有3个答案

逄征
2023-03-14

我想这是我能做的最好的了;改编@maress

@Produces @CaseContext
public CaseDTO getContextCase()  {
    return JSFUtils.getFromPageFlowScope("case", CaseDTO.class);
}

@Produces @CaseContext("ip")
public IPCaseDTO getContextIpCase()  {
    return JSFUtils.getFromPageFlowScope("case", IPCaseDTO.class);
}

@Produces @CaseContext("group")
public GroupCaseDTO getContextGroupCase()  {
    return JSFUtils.getFromPageFlowScope("case", GroupCaseDTO.class);
}

注释:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ FIELD, METHOD })
public @interface CaseContext {
    public String value() default "";
}

然后注射点

@Inject @CaseContext
private CaseDTO muwCase;

@Inject @CaseContext("group")
private GroupCaseDTO muwCase;

@Inject @CaseContext("ip")
private IPCaseDTO muwCase;
苏志
2023-03-14

我会在这方面做点什么:

public abstract class CaseDTO {
}

和子类,创建一个限定符。

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER})
public @interface CaseContext {

    @Nonbinding
    String value() default "";

}

@ApplicationScoped
public class CaseDTOProducer {

    @ApplicationScoped
    @CaseContext("")
    public CaseDTO produce(InjectionPoint ip) {
        //You can make the instantiation as complex as you want:
        final CaseContext caseContext = ip.getAnnotated().getAnnotation(CaseContext.class);
        switch (caseContext.value()) {
            case "ip":
                return new IpCaseDTO();
            case "group":
                return new GroupCaseDTO();
            default:
                throw new ContextException("Unknown Case Context");
        }
    }

}

然后注射点:

public class CaseService {

    @Inject 
    @CaseContext("ip")
    private CaseDTO caseDTO;

    @Inject 
    @CaseContext("group")
    private CaseDTO caseDTO;
}
陈知
2023-03-14

我想你可能误解了类型安全解决机制。CDI注入是基于有一组bean(在你的例子中是它们的生产者)和一组注入点(又名IP;你@Inject的地方)。现在这两个都有一组特定的类型和限定符。

为了注入IP,您需要有一个包含必需类型的bean,并且所有请求的限定符都是该bean提供的限定符的子集。

在生产者的情况下,Bean类型来自方法返回类型。在你的情况下,它将是类、每个超类和所有实现的接口(无论是直接的还是间接的)。

因此,在您的代码示例中,如果您只是@injectcasedto,您将得到不明确的依赖关系异常-所有三个生产者都会生成一个bean,其中还包含CaseDTO

另一方面,获得未满足的依赖关系异常意味着没有适合这种注入点的bean。在您的示例中,只有supertype producer意味着@InjectGroupCasedTo将因此异常而失败,因为GroupCaseDTO不属于您的生产者创建的bean类型。

至于你的问题的解决方案,你可以使用限定符。这就解决了注入超类型的问题。@maress在另一个答案中建议的也是一个好主意(例如,没有新的限定符,在现有限定符中使用一个值)

事实上,这是我想要的:一个生产者方法一个限定符注释,允许我注入上下文案例

您可以让一个限定符给出不同的结果,但是您需要基于其他一些属性来知道您想要哪一个。例如,你可以有:

@Produces
@CaseContext
public CaseDTO produce() {
  if (methodToDetermineConfiguration()) {
    return JSFUtils.getFromPageFlowScope("case", IPCaseDTO.class);
  } else {
    return JSFUtils.getFromPageFlowScope("case", GroupCaseDTO.class);
  }
}

当然,您需要以某种方式定义methodToDetermineConfiguration(),以了解您实际想要生成什么。不确定你有什么选择,只是分享你如何设置制作人的信息。

 类似资料:
  • 本文向大家介绍JavaScript中的继承之类继承,包括了JavaScript中的继承之类继承的使用技巧和注意事项,需要的朋友参考一下 继承简介       在JS中继承是一个非常复杂的话题,比其他任何面向对象语言中的继承都复杂得多。在大多数其他面向对象语言中,继承一个类只需使用一个关键字即可。在JS中想要达到继承公用成员的目的,需要采取一系列措施。JS属于原型式继承,得益于这种灵活性,我们既可以

  • 我在Hibernate中有道传承,下面是代码: 用户DAO: 我有一个域类用户和两个子类用户:Customer和Sales。我有两个dao类,分别用于客户和销售。 用户DAO: 客户道: 销售DAO: 我的问题是,当我使用CusterDap调用方法getUserByUsername()(继承自BaseDaoImpl)与销售的用户名(拥有用户名的用户是SalesRep的实例,而不是客户)时,它会抛出

  • 我正在为扩展了B类的a类编写单元测试。我正在使用Mockito,我想模拟一个组织。slf4j。这两个类都可以使用。问题是,当类A从类B调用方法时,模拟记录器没有被注入到类B中,所以我得到了一个NPE。有没有办法成功地测试这一点?

  • 如何在Gradle中清晰地分离可能需要两个不同配置任务的任务?我试图将要在buildsrc/dbhelpertasks.gradle文件中执行的实际任务与父build.gradle文件分开。build.gradle将包含在dbhelpertasks.gradle中使用的部分配置的任务。 我有许多不同的数据库要连接并在其上执行SQL,因此创建了一个采用数据库名称和URL的SQLServerTask。

  • 我一直在做一个基本的类继承练习,尽管我认为我已经掌握了它的jist,但我的程序并没有按应有的方式工作。我遇到了编译错误,但还没有弄清楚原因——如果你们都能在这里帮助我,那就太好了。 首先,这里有三个文件1。人java——基类2。大学生java——一个派生的Person类。java 3。家庭java——不太确定,我认为它是自己的基类 人java有两个实例变量,String name和int age,

  • 1、定义类的继承 说到继承,你一定会联想到继承你老爸的家产之类的。 类的继承也是一样。 比如有一个旧类,是可以算平均数的。然后这时候有一个新类,也要用到算平均数,那么这时候我们就可以使用继承的方式。新类继承旧类,这样子新类也就有这个功能了。 通常情况下,我们叫旧类为父类,新类为子类。 首先我们来看下类的继承的基本语法: class ClassName(BaseClassName): <st