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

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

鉴于:

  • 我使用 Weld 作为我的底层 CDI 框架实现。
  • 我有一个没有无参数构造函数的 ClassWithoutControl 类(即不是有效的 Bean)。
  • 我为该类创建了一个自定义 Bean。
  • 当触发 AfterBeandiscovery 事件时,我通过扩展添加此 bean。
  • 在这个 bean 上调用 create(CreationalContext ctx) 时,我构造了一个 ClassWithoutControl 类的新实例。
  • 我为该自定义 Bean 创建了一组注入点。
  • 其中一个注入点是 ClassWithControl 的字段。

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

换句话说,我如何为一个我无法控制的类构造一个自定义 bean,这样我仍然可以将一个我可以控制的类的实例注入特定字段?

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

    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 是一个类,它创建一个扩展 Bean 的 CustomBean 实例。 在 CustomBean 的 create(CreationalContext ctx) 函数调用创建者 BiFunction。 创建者的参数是传递给 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 实现),看看我是否能找到解决此问题的方法。 不幸的是,由于我无法控制的类中缺少无参数构造函数,因此我无法提供 InjectionTarget。 BeforeBeanDiscovery 显示该类的 bean 是由扩展添加的。但是,由于缺少无参数构造函数,因此永远不会创建 InjectionTarget。

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?