Java 继承权中类型的CDI注入

Java 继承权中类型的CDI注入,java,dependency-injection,cdi,jsf-2.2,oracle-adf,Java,Dependency Injection,Cdi,Jsf 2.2,Oracle Adf,我有一个超类型(CaseDTO)和几个子类型(GroupCaseDTO,IPCaseDTO),我想注入它们。开发环境是jdev12c 以下是两个注射点: 注入超类型(此注入点适用于两个子类型): @注入@CaseContext 私人案件到muwCase 注入特定子类型(此注入点仅适用于一个子类型): @注入@CaseContext 私人团体案例到muwCase 为了获得这些值,我尝试设置了许多生产者方法: // supertype @Produces @CaseContext public Ca

我有一个超类型(CaseDTO)和几个子类型(GroupCaseDTO,IPCaseDTO),我想注入它们。开发环境是jdev12c

以下是两个注射点:

  • 注入超类型(此注入点适用于两个子类型):

    @注入@CaseContext 私人案件到muwCase

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

    @注入@CaseContext 私人团体案例到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()]
    
    public class CaseService {
    
        @Inject 
        @CaseContext("ip")
        private CaseDTO caseDTO;
    
        @Inject 
        @CaseContext("group")
        private CaseDTO caseDTO;
    }
    
    只有两个子类型生成器方法也不起作用:

    :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()]
    
    我想我可以通过为我需要的每个子类型使用限定符注释来解决这个问题,但这似乎太过分了。如果没有大量的限定符注释,就没有办法让注入工作吗


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

    我想在这方面做点什么:

    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");
            }
        }
    
    }
    
    然后注入点:

    :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()]
    
    public class CaseService {
    
        @Inject 
        @CaseContext("ip")
        private CaseDTO caseDTO;
    
        @Inject 
        @CaseContext("group")
        private CaseDTO caseDTO;
    }
    

    我想你可能误解了我的意思。CDI注入基于拥有一组bean(在您的情况下,是它们的生产者)和一组注入点(又名IP;您
    @Inject
    的位置)。现在这两个都有一组类型和限定符

    为了注入IP,您需要有一个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()
    ,以了解您实际想要生成什么。不知道你有什么选择,只是分享你如何设置制作人的信息。

    我认为这是我能做的最好的了;改编@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;
    

    我无法在DTO类上添加注释,它们不在项目I的一部分中control@GregSt.Onge查看使用动态制作人进行的更新。这对我来说确实有效,只是需要根据我的情况调整技术。注释:我认为我们需要舍弃注释定义中的“非绑定”部分,如果您舍弃
    @Nonbinding
    ,然后,您必须为
    CaseContext
    的每个值创建一个producer方法。您的建议是否与我的第一个失败场景完全相同:仅包括超类型producer?在确定类型匹配时,CDI/WELD是否在producer方法上查看返回类型?还是在方法中寻找返回语句?如果是后者,那会让我大吃一惊:)这与您的第一次不一样,我试图向您解释这是如何工作的,以便您可以根据您的代码根据您的需要定制解决方案。你可以有一个生产者,如果你有办法决定每次注射时生产什么。至于你的第二个问题,我想你甚至没有费心打开我放在那里的文档的链接。第一行以-producer方法的bean类型取决于方法返回类型:不需要全部屈尊。当您知道我希望能够注入到GroupCaseDTO属性时,为什么建议使用一个返回类型CaseDTO的单一生产者方法?也许你没有读过你链接的文章?诚然,这仍然不是很好,因为我仍然需要每个子类型一个生产者方法…但是这比为每个子类型创建一个新的注释要好