Ответ 1
Раздел 3.3 спецификация CDI дает довольно хороший обзор высокого уровня использования @Produces
аннотация:
Метод-производитель действует как источник объектов для инъекций, где:
• объекты, подлежащие вводу, не обязательно должны быть экземплярами beans, или
• конкретный тип вводимых объектов может варьироваться во время выполнения, или
• объекты требуют некоторой пользовательской инициализации, которая не выполняется конструктором bean.
Скажем, например, что вы хотели бы переместить между управляемым компонентом Java EE, таким как менеджер объектов и другие компоненты CDI, вы могли бы использовать аннотацию @Produces
. Другим преимуществом является то, что вы избегаете дублирования аннотаций @PersistenceContext
на всем уровне домена данных.
class A {
@PersistenceContext // This is a JPA annotation
@Produces // This is a CDI 'hook'
private EntityManager em;
}
class B {
@Inject // Now we can inject an entity manager
private EntityManager em;
}
Еще одно удобное использование - это доступ к библиотекам, не имеющим CDI beans (например, без конструкторов по умолчанию):
class SomeTPLClass {
public SomeTPLClass(String id) {
}
}
class SomeTPLClassProducer {
@Produces
public SomeTPLClass getInstance() {
return new SomeTPLClass("");
}
}
Javadoc for производит также показывает интересный (но довольно редкий случай) создание именованной коллекции, которая впоследствии может быть введена в другой управляемый beans (очень классный):
public class Shop {
@Produces @ApplicationScoped
@Catalog @Named("catalog")
private List<Product> products = new LinkedList<Product>(8);
//...
}
public class OrderProcessor {
@Inject
@Catalog
private List<Product> products;
}
Контейнер отвечает за обработку всех методов и полей, помеченных аннотацией @Produces, и обычно будет делать это при развертывании вашего приложения. Обработанные методы и поля затем будут использоваться как часть разрешения точки впрыска для управляемого beans, если необходимо.