2012-06-21 16 views
7

Państwa specyfikacji JSR-299 w §3.1:ograniczeniami rodzajowych z CDI

Jeśli udało klasa fasola jest typem generycznym, musi mieć zakres @Dependent. Jeśli zarządzany komponent bean ze sparametryzowaną klasą komponentu bean zadeklaruje dowolny zakres inny niż @ niezależny, kontener automatycznie wykryje problem i potraktuje go jako błąd definicji.

Skutecznie co oznacza, że ​​nie można tego zrobić:

@Named 
@SessionScoped or @RequestScoped or similar 
public class MyProducer<T> {...} 

Jakie są przyczyny techniczne dla tej decyzji?

Czy zostanie to naprawione w nadchodzącej wersji CDI przez przypadek?

Czy istnieje najlepsza praktyka do radzenia sobie z tym problemem?

Dziękuję

EDIT - obejście mogę często wykorzystują to, aby wprowadzić ogólny POJO fasoli w fasoli z niezbędnego zakresu. Często, ale nie zawsze.

+0

Świetne pytanie, przy okazji.Nie wiedziałem o tym ograniczeniu i naprawdę cię to zastanawia. –

Odpowiedz

13

Oto rodzajowe, non-zależne klasa fasola:

@ApplicationScoped 
public class FavouriteChooser<T> { 
    public T getFavourite() { 
     // ... 
    } 
} 

Ile instancje tej fasoli będzie istniała w aplikacji?

Oto miejscu wstrzyknięcia:

@Inject 
private FavouriteChooser<String> favouriteWord; 

A oto kolejny:

@Inject 
private FavouriteChooser<Integer> favouriteNumber; 

Chcesz zmienić swoją odpowiedź? : D

Ooh, i tu jest inny:

@Inject 
private FavouriteChooser<CharSequence> favouriteLetters; 

EDIT. Jeśli chcesz rozwiązania, sugerowałbym, aby twoja klasa generyczna była abstrakcyjna i dodawała konkretne podklasy, które wiążą ten typ. A więc:

public abstract class MyProducer<T> {...} 

@Named 
@SessionScoped 
public class MyStringProducer extends MyProducer<String> {} 

@Named 
@SessionScoped 
public class MyIntegerProducer extends MyProducer<Integer> {} 

Jest to szablonowy plan, ale to tylko trzy linie na typ. Pamiętaj, że dałoby to jedną instancję przypadającą na sesję dla każdego typu, którego możesz nie chcieć.

+0

Nice - tak długo, dopóki nie nazwiesz fasoli, możesz go wstrzyknąć? Jeśli scoping jest zachowywany (czy jest? - czy każdy z nich ma zakres zastosowania FavouriteChooser?), Jedynym ograniczeniem jest to, że nie mogę uzyskać do nich dostępu za pomocą eksploracji EL? I nie jest sprzeczne z spec? W końcu powinna to być zarządzana fasola. – kostja

+3

Nie, chodzi mi o to, że ten kod nie może działać! Zadeklarowałem zakres aplikacji "FavouriteChooser", co oznacza, że ​​może istnieć tylko jedna instancja. Ale są tam dwa miejsca wstrzyknięć, które * nie mogą być zaspokojone przez ten sam obiekt *. I myślę, że dlatego nie można wstrzykiwać instancji klas ogólnych w jakimkolwiek innym zakresie niż zależny. –

+0

Przepraszam za brak jasności co do tego, co próbowałem powiedzieć, kiedy napisałem tę odpowiedź. Po prostu rzuciłem to bez czasu na wyjaśnienia: /. –

2

Wszystkie niezespolone ziarna o określonym rozmiarze muszą być proxy - AFAIK nie jest to możliwe w przypadku typów ogólnych.

UPDATE:

Chciałbym móc wyjaśnić bardziej szczegółowo, ale nie jestem ;-) Weld korzysta javassist, a oni twierdzą, że proxying generic types is possible in principle - choć nie bezpośrednio obsługiwane przez będąc w głównym API . Ale mówimy o specyfikacji, a nie o wykonaniu Weld ...

Może ktoś inny może wypełnić lukę?

+0

Dzięki, jan. Rzuca to już pewne światło - byłoby wspaniale, gdybyś mógł również wyjaśnić, dlaczego typy ogólne nie mogą być proxy (domyślam się, że ma to coś wspólnego z główną nemezis java - typem wymazania, ale nie mogę tego położyć). – kostja