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

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

鉴于:

如何确保 CDI 将注入 InjectionPoint 所需类型的实例?

换句话说,如何为我无法控制的 class 构建自定义 bean,以便我仍然可以注入 class 的实例我确实可以控制特定领域?

我当前的(非功能性)代码如下所示:

    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 是一个 class,它创建一个扩展 Bean 的 CustomBean 实例。 创建者 BiFunction 在 CustomBean 的 create(CreationalContext ctx) 函数中被调用。 创建者的参数是传递给 create() 的 CreationalContext 和 CustomBean (this)。

我知道为什么以上不起作用。 Weld 返回 NonProducibleInjectionTarget,因为 weld 用来创建 InjectionTarget 的 AnnotatedType 没有无参数构造函数。 但是,我正在寻找一种无需依赖 Weld 的内部实现即可执行此操作的方法。 我找不到一种方法来欺骗 CDI 接受我的 ClassWithoutControl 实例,同时重新训练注入另一个实例的能力。

我看过 https://docs.jboss.org/weld/reference/latest/en-US/html_single/#_wrapping_an_injectiontarget 但我不太明白如何创建这样的包装器。因此,在这方面的任何帮助也将不胜感激。

我深入研究了 Weld(我当前的 CDI 实现)以查看是否可以找到解决此问题的方法。 不幸的是,由于我无法控制的 class 中缺少无参数构造函数,我无法提供 InjectionTarget。 BeforeBeanDiscovery 显示扩展正在添加 class 的 bean。然而,由于它缺少无参数构造函数,因此永远不会创建 InjectionTarget。

我试图通过在 ProcessAnnotatedType 期间包装 AnnotatedType 并插入 AnnotatedConstructor 并将其与原始 AnnotatedType 的构造函数一起返回来解决此问题。这是可以做到的,不幸的是 AnnotatedConstructor 有一个 getJavaMember() 方法,它 returns 原始构造函数。在我的例子中,Constructor (java-member) 不存在,因为您无法实例化 Constructor 的新实例。这是一条死胡同,因为没有其他方法可以获取构造函数的自定义实例。

我现在正在探索字节码操作库,例如 byte-buddy。这些将使我能够在 运行 时间添加一个无参数构造函数。对我来说不会有任何影响,因为无参数构造函数的唯一目的是确保 CDI 将 class 标记为有效 Bean。