【问题标题】:How to use CDI to inject into an object instantiated by 3rd party如何使用 CDI 注入由第 3 方实例化的对象
【发布时间】:2018-10-02 16:59:53
【问题描述】:

我有一个由 3rd 方代码实例化的类(它使用反射来创建对象。)我提供了他们接口的实现,他们创建了对象。在我的实现中,我想使用 CDI 来注入执行逻辑的服务。这样做的正确方法是什么?

public interface ThirdPartyInterface {
    public void DoSomething();
}

public class InjectedService {
    public void DoSomeLogic() { ... }
}

public class MyImplementation implements ThirdPartyInterface {
    @Inject InjectedService service;

    @Override
    public void DoSomething() {
        service.DoSomeLogic();
    }
}

我最初认为这可以通过 CDI 的魔力实现,但发现我的服务对象为空。

到目前为止,我唯一想到的就是在构造函数中手动注入服务

 public MyImplementation() {
     CDI<Object> cdi = CDI.current();
     service = cdi.select(InjectedService.class).get();
 }

这是获取实例的正确/唯一/最佳方式吗?我将 Weld 用于我的 CDI 实施。

我还发现它在构造函数中也可以工作:

    public MyImplementation() {
        CDI<Object> cdi = CDI.current();
        BeanManager bm = cdi.getBeanManager();
        AnnotatedType<MyImplementation> myType = bm.createAnnotatedType(MyImplementation.class);
        Set<Bean<?>> beans = bm.getBeans(MyImplementation.class);
        Bean<?> bean = bm.resolve(beans);
        @SuppressWarnings("unchecked")
        CreationalContext<MyImplementation> cc = (CreationalContext<MyImplementation>)bm.createCreationalContext(bean);
        bm.createInjectionTarget(myType).inject(this, cc);
   }

【问题讨论】:

  • 你几乎找到了。您要么需要故意让 CDI 为您提供托管版本,要么需要通过 JNDI 查找 bean。如果封闭 bean 是通过反射创建的,则与使用“new”相同,不会从 CDI 的角度进行管理。

标签: java dependency-injection cdi weld


【解决方案1】:

只要有人手动创建对象,CDI 默认不会向其中注入任何内容。

您使用构造函数注入的方法可能会起作用,除非您进入 EAR 等,CDI.current() 可能无法达到您的预期。

有一种方法可以使 CDI 注入手动创建的对象 - 第 3 方必须采取此步骤才能使其工作。你需要BeanManager 和一个你想注入的实例:

        BeanManager beanManager = ...; // get hold of bean manager, can be injected
        CreationalContext<Object> ctx = beanManager.createCreationalContext(null);
        @SuppressWarnings("unchecked")
        InjectionTarget<MyImplementation> injectionTarget = (InjectionTarget<MyImplementation>) beanManager
            .getInjectionTargetFactory(beanManager.createAnnotatedType(myImplementationInstance.getClass())).createInjectionTarget(null);
        injectionTarget.inject(myImplementationInstance, ctx);

注意 - 通过这样做,您有责任在不再需要该对象后对其进行清理。将CreationContext 存储在某处并在其上调用release() 方法以便正确处理它(使用所有可能的预销毁调用等)。

另外,既然您已经在使用 CDI,为什么第 3 方不简单地 @Inject 您提供的 bean?

【讨论】:

  • 好吧,在这种情况下,第三方是 Microsoft,我正在使用他们的应用程序洞察库,并希望通过我在他们扫描的 xml 文件中注册的 TelemetryInitializer 接口提供其他属性。他们使用反射创建了我的类的一个实例,但我已经构建了检索我想要设置的属性的服务,所以希望能够注入它们。
  • 嗨!我应该将每个 Bean 的 CreationalContext 存储为“注入”吗?
猜你喜欢
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
  • 2014-12-11
  • 1970-01-01
相关资源
最近更新 更多