2014-04-10 27 views
8

aşağıda gibi kod kullanıyorum:CDI @ Produces ile belirsiz bağımlılık - neden?

public Configuration { 

    private boolean isBatmanCar = someMethod(...); 

    @Produces 
    public Car getCar(@New Car car) { 
     if(isBatmanCar) { 
      car.setName("BatmanCar"); 
     } 
     return car; 
    } 
} 

public Car { 
    private String name = "NormalCar"; 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

public Demo { 
    @Inject 
    Car car; 

    // rest of code 
} 

ben biliyorum

AmbiguousResolutionException: WELD-001318 Cannot resolve an ambiguous dependency between (...) Car with qualifiers [@Any @Default] (...) Producer Method [Car] with qualifiers [@Any @Default]

olsun (Btw Java EE 6) glassfish için bir uygulama dağıtırken ben Araç sınıfına @Alternative eklerken işe yarayacak, ama bunu yapmanın uygun yolu olup olmadığını merak ediyorum ve neden bunu yapmak zorundayım?

Bu durumda @ Produces'in doğru kullanımının ne olduğunu söyleyebilir misiniz?

Java EE 6, CDI 1.0, EJB 3.1, glassfish 3.2

cevap

12

hata 2 sınıf olmak tip Car, biri fasulye, diğer yapımcı olmak zorunda olmasından kaynaklanır kullanıyorum. Belirsizliği gidermek için 2 belirgin çözümünüz var:

İlk olarak, mantığı orijinal sınıfında (örneğin bir kurucuda veya örneğin @PostConstruct yönteminde) ve üreticinizi kaldırın. Bu sadece bir Car fasulye kaldı.

Yoksa gerçekten 2 fasulye var istiyorum ya da üretilen fasulye için bir ön eleme oluşturmalıdır bunu önlemek olamazsa:

@Target({ TYPE, METHOD, PARAMETER, FIELD }) 
@Retention(RUNTIME) 
@Documented 
@Qualifier 
public @interface BatmanChecked { 
} 

ve yapımcı üzerinde kullanmak

@Produces 
@BatmanChecked 
public Car getCar(Car car) {...} 

araç, enjekte edilemeyen enjeksiyonu çözmek için doğal seçeneğidir. @Alternative'u kullanmak da işe yarıyor ama burada iyi bir uygulamadan çok daha fazla bir hiledir.

Son yorum: @New, Car fasulyesinin kapsamı dışında olduğundan (bu nedenle @Dependent scoped). @Yeni bir üretici sadece @Dependent olmayan bir kapsamı olan bir fasulye enjekte ettiğinde yararlıdır. Bu kod, Car sınıfınızın kapsamı @Dependent kapsamındaysa bu kod pek kullanışlı değildir.

+0

@Alternative kullanımıyla ilgili iyi uygulama nedir? – dmydlarz

+0

@Alternative, aynı fasülye (tip) için farklı bir sürüm önermenizi ve bir yapılandırma dosyasında yapılandırmayla etkinleştirmenizi sağlar. Dev/testte ve üretimde farklı bir ben'e sahip olmak için, örneğin, yalnızca fasulyeler.xml dosyasında değiştirmek için kullanılabilir. –

5

başka olasılık böyle Araç sınıfında olmayan varsayılan kurucu oluşturmak olacaktır:

public Car { 
    private String name = "NormalCar"; 

    public Car(String name) { 
     this.name = name; 
    } 
    ... 
} 

varsayılan kurucu kaldırarak, Araba sınıfı artık enjeksiyon yoluyla kullanılan örneklerini oluşturmak için de kullanılabilir.

Ve

@Produces 
public Car getCar() { 
    if(isBatmanCar) { 
     return new Car("BatmanCar"); 
    } 
    return new Car("NormalCar"); 
} 

için yapımcı yöntemini değiştirmek ardından yapımcı yöntemi Otomobiller oluşturmak için tek yol olacaktır.

Her zaman, özelleştirilmiş örneğe gereksiniminiz olduğunu ve varsayılan kurucuya ihtiyacınız olmadığını bildiğinizde kullanılabilir. Ama genellikle Antoine çözümü daha kullanışlıdır.

8

@Alternatif çalışmaların kullanılması ancak yalnızca beans.xml aracılığıyla etkinleştirilebilmesi için kullanılmalıdır.

Fasonuzun varsayılan yapıcısını bastırmak da işe yarıyor, ancak fasulyenizi @RequestScoped'ten başka bir kapsamda kullanamayacaksınız.

Kendi niteleyici çalışmalarınızı kullanmak, ancak yalnızca bir uygulamanız varsa ve yalnızca kurucunuzu üreticisinden ziyade bir prodüktörle eşleştirebilmek istiyorsanız çok kullanışlıdır. Aklınızda tutmak zorunda

@Any 
public class Car { 
} 
... 
@Produces 
public Car getCar() { 
    return new Car(); 
} 
... 
@Inject 
Car car; 

şeyler::

  • Tüm fasulye ve üreticilerin her zaman örtük nitelikli @Any
  • en kolay yolu fasulye açıklama için @Any olduğunu Açık niteleyiciler olmaksızın fasulye ve üreticiler zımnen niteliklidir @Default

  • Açık niteleyicileri olan fasulye ve üreticiler artık kesin bir şekilde kalifiye değildir. ied @Default
  • açık elemeleri olmadan
  • Enjeksiyon noktaları örtük nitelikli @Default vardır, ama tüm bu İlişkin

@Any değil, böyle aynı kod yukarıdaki gibi açıkça nitelikli görünüyor:

@Any 
public class Car { 
} 
... 
@Produces 
@Any 
@Default 
public Car getCar() { 
    return new Car(); 
} 
... 
@Inject 
@Default 
Car car; 

It Fasonun varsayılan kurucusunun enjeksiyon noktası için geçerli bir olasılık olmadığı ve üreticinin geçerli bir olasılık olduğu daha açık hale gelir.