2013-02-25 18 views
11

Załóżmy, że mam klasę samochodów. W moim kodzie chcę utworzyć 10 samochodów. Klasa samochodów zawiera pewne adnotowane zależności @Inject. Jakie byłoby najlepsze podejście do tego?Tworzenie instancji w locie w CDI

CDI posiada interfejs Provider, który można używać do tworzenia samochodzie

@Inject Provider<Car> carProvider; 
public void businessMethod(){ 
    Car car = carProvider.get(); 
} 

Niestety to nie działa, jeśli nie masz CarFactory że ma metodę z @Produces adnotacji który tworzy samochód. O ile odzwierciedla rzeczywisty świat, że nie mogę tworzyć samochodów bez fabryki, wolałbym nie pisać fabryk na wszystko. Po prostu chcę, żeby kontener CDI tworzył mój samochód, tak jak każdą inną fasolę. Jak polecasz tworzyć te samochody?

Odpowiedz

8

Wystarczy użyć interfejsu javax.enterprise.inject.Instance zamiast.

Jak to:

public class Bean { 

    private Instance<Car> carInstances; 

    @Inject 
    Bean(@Any Instance<Car> carInstances){ 
     this.carInstances = carInstances; 
    } 

    public void use(){ 
     Car newCar = carInstances.get(); 
     // Do stuff with car ... 
    } 

} 
+0

W rzeczywistości to właśnie wykorzystałem.Czy możesz naprawić swój przykład, argument konstruktora nie jest tego samego typu, co atrybut class: Car vs UIModule. Myślę również, że wstrzyknięcie powinno być annotetade z @New zamiast @Any. Lepszym przykładem użycia metody use() byłoby pokazanie, w jaki sposób można uzyskać instancję samochodu. Na przykład 'carInstances.get()' – palto

+0

@New jest uznawane za przestarzałe w CDI 1.1, a nie w komponentach @Dependent. Zobacz CDI 1.1, sekcja 3.14. Nie rozumiem, co jest złego w korzystaniu z dostawcy, ja. e., 'CDI.current(). select (Car.class) .get()'? –

+0

@MartinAndersson Pierwotny problem polegał na tym, że musiałem stworzyć fabrykę do korzystania z dostawcy. Przykład podany w komentarzu jest dla mnie całkowicie nowy. Może mógłbyś z tego stworzyć odpowiedź? – palto

2

Można użyć kwalifikatorów ze swoimi @Produces adnotacji:

@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER}) 
public @interface MyCars { 
} 

próbka-producent-metoda:

@Produces 
@MyCars 
public Car getNewCar(@New Car car){ 
    return car; 
} 

Wykorzystanie:

@Inject 
@MyCars 
private Provider<Car> carProvider; 
+0

'@Nowa jest przestarzała w CDI 1.1, a nie w komponentach @Dependent. Zobacz CDI 1.1, sekcja 3.14. –

+0

@MartinAndersson Wiem o tym, ale jako czas odpowiedzi CDI 1.1 nie było, więc odpowiedź trafia do CDI 1.0 (tylko po to, aby wyjaśnić to tutaj) – FibreFoX

0

Innym sposobem na to byłoby na proste nie daje Carowi żadnego zakresu CDI, który uzależnia i dostaniesz nową instancję za każdym razem, gdy zostanie wstrzyknięta i t wystąpienia węża nie zostaną zniszczone, dopóki nie zostanie zniszczona instancja zawierająca.

+0

zakres nie jest czymś, o co trzeba się martwić, o ile rozumie się, że chciał mieć wstrzykniętego producenta i nie musiał implementować konkretnej klasy producenta. Masz rację, że wszystkie wstrzyknięte cdi-fasole stają się "zależne", ale czy to nie to, co palto mówiło o – FibreFoX

+0

"nowej instancji za każdym razem, gdy jest wstrzykiwane"? W jaki sposób osoba uzależniona może zostać wstrzyknięta "za każdym razem"? Injection dzieje się tylko raz. Of proxy. Jeśli zostanie zaimplementowany @ Provied bean lub proxy, każde wywołanie tego proxy będzie zawsze kierowane do jednego i tego samego komponentu bean. –

+0

To wstrzykuje proxy raz, tak, ale jeśli to proxy rozwiąże problem z zależną skalą, wówczas ten zależny zakresowy komponent zostanie utworzony nowy dla każdej nowej instancji komponentu bean żądającego wtrysku. Wstrzyknięta fasola staje się zależna od cyklu życia innych. – LightGuard

5

Mój ulubiony model programowy odnośnika jest użycie CDI.current().select().get().

Wykazano .

Aplet ma zależność od dwóch ziaren CDI, jedna prośba scoped a druga aplikacja scoped:

private final RequestScopedBean requestScoped 
      = CDI.current().select(RequestScopedBean.class).get(); 

private final ApplicationScopedBean applicationScoped 
      = CDI.current().select(ApplicationScopedBean.class).get(); 

Klasa test, który wykorzystuje ten aplet można znaleźć here.

Sprawdź kod, a zauważysz, że kod jest w pełni równoważny z tym, co można uzyskać za pomocą @Inject MyBean myBean;.