簡體   English   中英

如何確保 Java CDI 框架實現將在自定義 bean 的自定義注入點注入實例?

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

鑒於:

  • 我使用 Weld 作為我的底層 CDI 框架實現。
  • 我有一個 class ClassWithoutControl 沒有無參數構造函數(又名不是有效的 Bean)。
  • 我為該 class 創建了一個自定義 Bean。
  • 當觸發 AfterBeanDiscovery 事件時,我通過擴展添加此 bean。
  • 當在這個 bean 上調用 create(CreationalContext<> ctx) 時,我構造了一個新的 class ClassWithoutControl 實例。
  • 我為該自定義 Bean 創建了一組注入點。
  • 其中一個 InjectionPoints 是 ClassWithControl 的一個字段。

如何確保 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) function 中被調用。 創建者的參數是傳遞給 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() 方法,它返回原始構造函數。 在我的情況下,構造函數(java-member)不存在並且看到你無法實例化構造函數的新實例。 這是一個死胡同,因為沒有其他方法可以獲取構造函數的自定義實例。

我現在正在探索字節碼操作庫,例如 byte-buddy。 這些將使我能夠在運行時添加一個無參數構造函數。 對我沒有任何影響,因為無參數構造函數的唯一目的是確保 CDI 將 class 標記為有效 Bean。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM