Как использовать CDI для внедрения в объект, созданный третьей стороной - PullRequest
0 голосов
/ 02 октября 2018

У меня есть класс, для которого создается сторонний код (он использует отражение для создания объекта). Я предоставляю реализацию их интерфейса, и они создают объект.В моей реализации я хочу использовать 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);
   }

1 Ответ

0 голосов
/ 03 октября 2018

Пока кто-то создает объект вручную, 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 боб, который вы предоставляете?

...