简体   繁体   English

如何确保 Java CDI 框架实现将在自定义 bean 的自定义注入点注入实例?

[英]How to ensure a Java CDI framework implementation will inject an instance at a custom injectionpoint of a custom bean?

Given that:鉴于:

  • I am using Weld as my underlying CDI framework implementation.我使用 Weld 作为我的底层 CDI 框架实现。
  • I have a class ClassWithoutControl without a no-arg constructor (aka not a valid Bean).我有一个 class ClassWithoutControl 没有无参数构造函数(又名不是有效的 Bean)。
  • I create a custom Bean for that class.我为该 class 创建了一个自定义 Bean。
  • I add this bean via an Extension when a AfterBeanDiscovery event is triggered.当触发 AfterBeanDiscovery 事件时,我通过扩展添加此 bean。
  • When create(CreationalContext<> ctx) is called on this bean I construct a new instance of class ClassWithoutControl.当在这个 bean 上调用 create(CreationalContext<> ctx) 时,我构造了一个新的 class ClassWithoutControl 实例。
  • I have created a set of InjectionPoints for that custom Bean.我为该自定义 Bean 创建了一组注入点。
  • One of those InjectionPoints is a field of ClassWithControl.其中一个 InjectionPoints 是 ClassWithControl 的一个字段。

How do I ensure that CDI will inject an instance of the type required by the InjectionPoint?如何确保 CDI 将注入 InjectionPoint 所需类型的实例?

In other words, how do I construct a custom bean for a class over which I have no control, in such a way that I can still inject an instance of a class over which I do have control into a particular field?换句话说,我如何为我无法控制的 class 构造一个自定义 bean,这样我仍然可以将我可以控制的 class 的实例注入到特定字段中?

My current (non-functional) code looks like this:我当前的(非功能性)代码如下所示:

    void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager beanManager) {
    final AnnotatedType<ClassWithoutControl> annotatedType = beanManager.createAnnotatedType(ClassWithoutControl.class);
    AnnotatedField<ClassWithoutControl> annotatedField = null;
    for (AnnotatedField<? super ClassWithoutControl> field : annotatedType.getFields()) {
        if ("field".equals(field.getJavaMember().getName()) && ClassWithControl.class.equals(field.getJavaMember().getType())) {
            annotatedField = (AnnotatedField<ClassWithoutControl>) field;
            break;
        }
    }
    final InjectionPoint injectionPoint = beanManager.createInjectionPoint(annotatedField);
    final HashSet<InjectionPoint> injectionPoints = new HashSet<>();
    injectionPoints.add(injectionPoint);
    BiFunction<CreationalContext<ClassWithoutControl>, Bean<ClassWithoutControl>, ClassWithoutControl> creator = (creationalContext, bean) -> {
        final InjectionTarget<ClassWithoutControl> injectionTarget = beanManager.createInjectionTarget(annotatedType);
        ClassWithoutControl instance = new ClassWithoutControl(this.paramater1, this.parameter2);
        injectionTarget.inject(instance, creationalContext);
        injectionTarget.postConstruct(instance);
        return instance;
    };
    customBeanBuilder.setInjectionPoints(injectionPoints).setCreator(creator);
    final BeanAttributes<ClassWithoutControl> beanAttributes = beanManager.createBeanAttributes(annotatedType);
    customBeanBuilder.setBeanAttributes(beanAttributes);
    abd.addBean(customBeanBuilder.build());
}

CustomBeanBuilder is a class which creates an instance of CustomBean which extends Bean. CustomBeanBuilder 是一个 class ,它创建一个扩展 Bean 的 CustomBean 实例。 The creator BiFunction is called in the create(CreationalContext ctx) function of a CustomBean.创建者 BiFunction 在 CustomBean 的 create(CreationalContext ctx) function 中被调用。 The creator's parameters are the CreationalContext as passed to create() and a CustomBean (this).创建者的参数是传递给 create() 的 CreationalContext 和 CustomBean (this)。

I know why the above does not work.我知道为什么上述方法不起作用。 A NonProducibleInjectionTarget is returned by Weld, since the AnnotatedType that is used by weld to create the InjectionTarget has no no-args constructor. Weld 返回 NonProducibleInjectionTarget,因为 Weld 用于创建 InjectionTarget 的 AnnotatedType 没有无参数构造函数。 I am however looking for a way that I can do this, without having to depend on Weld's internal implementations.然而,我正在寻找一种方法可以做到这一点,而不必依赖 Weld 的内部实现。 I can't find a way to trick the CDI into accepting my instance of ClassWithoutControl while retraining the ability to inject another instance.在重新训练注入另一个实例的能力时,我找不到一种方法来欺骗 CDI 接受我的 ClassWithoutControl 实例。

I have looked at https://docs.jboss.org/weld/reference/latest/en-US/html_single/#_wrapping_an_injectiontarget but I do not quite understand how to create such a wrapper.我看过https://docs.jboss.org/weld/reference/latest/en-US/html_single/#_wrapping_an_injectiontarget但我不太明白如何创建这样的包装器。 So any help in that direction would be appreciated as well.因此,我们也将不胜感激这方面的任何帮助。

I dove into Weld (my current CDI implementation) to see if I could find a way to resolve this.我深入研究 Weld(我当前的 CDI 实现),看看我是否能找到解决这个问题的方法。 Unfortunately I cannot provide the InjectionTarget due to the missing no-args constructor in the class I do not control.不幸的是,由于我无法控制的 class 中缺少无参数构造函数,我无法提供 InjectionTarget。 BeforeBeanDiscovery reveals that the bean for the class is being added by the Extension. BeforeBeanDiscovery 显示扩展正在添加 class 的 bean。 However due to the fact that it is missing the no-args constructor an InjectionTarget is never created.然而,由于它缺少无参数构造函数,因此永远不会创建 InjectionTarget。

I've attemped to resolve this by wrapping the AnnotatedType during ProcessAnnotatedType and inserting a AnnotatedConstructor and returning it with the constructors of the original AnnotatedType.我试图通过在 ProcessAnnotatedType 期间包装 AnnotatedType 并插入 AnnotatedConstructor 并将其与原始 AnnotatedType 的构造函数一起返回来解决此问题。 This can be done, unfortunately AnnotatedConstructor has a getJavaMember() method which returns the original Constructor.这可以做到,不幸的是 AnnotatedConstructor 有一个 getJavaMember() 方法,它返回原始构造函数。 In my case that Constructor (java-member) does not exist and seeing as you cannot instantiate a new instance of Constructor.在我的情况下,构造函数(java-member)不存在并且看到你无法实例化构造函数的新实例。 This was a dead end as there are no other means of obtaining a custom instance of Constructor.这是一个死胡同,因为没有其他方法可以获取构造函数的自定义实例。

I'm now exploring byte-code manipulation libraries such as byte-buddy.我现在正在探索字节码操作库,例如 byte-buddy。 These would enable me to add a no-args constructor at run-time.这些将使我能够在运行时添加一个无参数构造函数。 There would be no repercussions for me as the no-args constructor sole purpose is to ensure that CDI marks the class as a valid Bean.对我没有任何影响,因为无参数构造函数的唯一目的是确保 CDI 将 class 标记为有效 Bean。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM