Подтвердить что ты не робот

Пожалуйста, объясните аннотацию @Produces в CDI

Я читал о аннотации @Produces в CDI, но я не понимаю его использования.

public class Resources {

// Expose an entity manager using the resource producer pattern
@SuppressWarnings("unused")
@PersistenceContext
@Produces
private EntityManager em;                                        // 

@Produces
Logger getLogger(InjectionPoint ip) {                            // 
    String category = ip.getMember()
                        .getDeclaringClass()
                        .getName();
    return Logger.getLogger(category);
}

@Produces
FacesContext getFacesContext() {                                 // 
    return FacesContext.getCurrentInstance();
}

}

взято из: http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/guide/GreeterQuickstart/#GreeterQuickstart-

Как известно контейнеру для вызова метода производителя? Если я добавляю EntityManager, как контейнер вызывает @создает EntityManager? И как будет вызван метод производителя getLogger?

Я также не вижу причины, чтобы преодолеть все проблемы.

4b9b3361

Ответ 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, если необходимо.

Ответ 2

Пример не совсем для меня. Какая работа была незначительной:

@Alternative
class SomeTPLClass {
    public SomeTPLClass(String id) {
    }
}

class SomeTPLClassProducer {
    @Produces
    public SomeTPLClass getInstance() {
        return new SomeTPLClass("");
    }
}

Поэтому мне пришлось добавить @Alternative в мой класс, чтобы избавиться от ошибки, что для @Default было два параметра.