Петля впрыска CDI

У меня возникла проблема с внедрением CDI в контейнер Weld в JBoss 7.1.1.

У меня есть следующая объектная модель:

@Stateless
class ServiceEjb {
@Inject
A a;
}

class A {
@Inject
B b;
}

class B {
@Inject
A a;
}

При попытке внедрить A или B в мой класс без сохранения состояния цикл внедрения и сбой с javax.enterprise.inject.CreationException.

Я пробую многое (обзор, @Singleton на A или B, но безуспешно). Я не хочу ломать код, и эти инъекции имеют смысл.

Любые подсказки будут высоко оценены.


person jmcollin92    schedule 08.03.2013    source источник


Ответы (3)


Циклическое внедрение зависимостей не требуется стандартом CDI, если только хотя бы один компонент в цикле имеет нормальную область действия. Самое простое решение — задать для A или B нормальную область видимости. Если вы не можете указать ни одну из них (из макета кода, похоже, что все они имеют по умолчанию @Dependent псевдо -scope), вам придется искать другие решения. Публикация примера реального кода может помочь нам с конкретным решением, но вот начало:

  • Можно ли объединить A и B в один класс?
  • Можно ли выделить новый класс С из А и В так, чтобы А и В были @Inject С вместо друг друга?

Вот несколько ссылок SO с другими решениями, которые могут оказаться полезными:

MVP с CDI; избегать циклической зависимости

https://stackoverflow.com/questions/14044538/how-to-avoid-cdi-circular-dependency

person Nick    schedule 08.03.2013
comment
Спасибо за быстрый ответ. Должен признаться, что понятие нормального размаха для меня не очень понятно. Ссылки, которые вы предоставляете, говорят о @NormalScope, но этого не существует. Как объявить нормальный объем? - person jmcollin92; 09.03.2013
comment
Большинство областей являются обычными областями. Сеанс, приложение, беседа и области запросов являются обычными областями. Это отличается от псевдоскопов: одноэлементных и зависимых (что используется по умолчанию, когда вы не пишете аннотацию области действия). - person Nick; 09.03.2013
comment
Итак, поскольку я уже пытаюсь объявить область действия, это должно сработать, если я правильно понимаю. В какой области я могу попробовать DAO (доступ к SessionBean)? - person jmcollin92; 09.03.2013
comment
Спасибо за вашу помощь ! У меня это работает с @ApplicationScoped ! Не знаю, стоит ли иметь DAO ApplicationScoped. Является ли это эквивалентом Singleton в случае банки EJB. - person jmcollin92; 09.03.2013

Я решил проблему, используя javax.inject.Provider. явно. Хотя я чувствую, что WELD должен делать это под капотом автоматически, для меня это было не так. Это сработало для меня и решило мою связанную проблему.

class A {
    @Inject
    Provider<B> b; // access with b.get()
}

class B {
    @Inject
    Provider<A> a; // access with a.get()
}

Я не проверял это, но может быть достаточно использовать один Provider, чтобы разорвать цикл, т.е. вам не нужно использовать его в обоих классах.

person jan    schedule 23.06.2014

Вы должны внедрить экземпляр ‹B› вместо B (и/или экземпляр ‹A› вместо A)

person Sheepy    schedule 15.01.2015