如何使用CDI注入由第三方实例化的对象

时间:2018-10-02 16:59:53

标签: java dependency-injection cdi weld

我有一个由第三方代码实例化的类(它使用反射来创建对象。)我提供了其接口的实现,并且他们创建了对象。在我的实现中,我想使用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的魔力,但是发现我的服务对象为null。

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

 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);
   }

1 个答案:

答案 0 :(得分:1)

只要有人手动创建对象,默认情况下CDI就不会向其中注入任何东西。

除非您进入EAR且CDI.current()可能无法达到您的期望,否则采用构造函数注入的方法可能会奏效。

有一种方法可以使CDI注入到手动创建的对象中-第三方必须采取此步骤才能使其工作。您需要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,为什么第三方不简单@Inject您提供的bean?