2013-05-14 3 views
35

Я читал о аннотации @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?

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

+0

Это красота аннотации ... :) –

ответ

59

Раздел 3.3 CDI specification дает довольно хороший обзор высокого уровня использования @Produces аннотацию:

Производитель метод выступает в качестве источника объектов, подлежащие закачиваемых, где:

• объекты, подлежащие инжекции, не обязательно должны быть экземплярами бобов, или
• конкретный тип объектов, подлежащих впрыску, может варьироваться во время выполнения, или
• объекты требуют некоторой пользовательской инициализации, которая не выполняется конструктором 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 дружественные бобы (например, по умолчанию Конструкторы нет):

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

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

Javadoc для производит также показывает интересный (но довольно редко случай) производить именованный сбор, который может впоследствии быть введен в другие управляемые бобы (очень круто):

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

контейнер отвечает за обработку всех методы nd, помеченные аннотацией @Produces, и обычно это будет делать, когда ваше приложение будет развернуто. Обработанные методы и поля затем будут использоваться как часть разрешения точки впрыска для управляемых компонентов, если это необходимо.

+0

Хороший ответ. Thx для этого. Но у меня есть вопрос относительно вашего первого примера. Предположим, что 'Class C'soso' @ Производит' 'EntityManager'. Откуда «класс B» знает, какие из них вводить? – Reitffunk

+2

@Produces можно использовать только один раз по классу – Tex

+1

@Первис - я очень ценю ваши усилия здесь, и я думаю, что вы добавили отличный контент.Однако для новичков JavaEE я до сих пор не вижу, что делает аннотация? В первом примере с EntityManager, почему добавление этой аннотации делает так, что вы можете использовать @Inject? Кроме того, что означает, что «метод производителя действует как источник объектов, которые должны быть введены», точно означает? Что значит быть источником объектов? –

0

Пример не совсем для меня. Что ДИТ работа была незначительная подстройка:

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

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

Так я должен был добавить @Alternative на моем классе, чтобы избавиться от ошибок, которые были два варианта @default.

Смежные вопросы