طريقة منتج CDI العامة لا تعمل كما هو متوقع

StackOverflow https://stackoverflow.com/questions/4303514

  •  29-09-2019
  •  | 
  •  

سؤال

لدي طريقة منتج CDI - اعتمادًا على بعض الظروف غير ذات صلة بهذا المثال - ينشئ كائنات من أنواع مختلفة:

public class TestProducer {

  @Produces @TestQualifier
  public Object create(InjectionPoint ip) {
    if(something) {
      return "a String";
    } else {
      return Integer.valueOf(42);
    }
  }

ولكن عند استخدام هذا المنتج ، أحصل دائمًا على خطأ في حالة المتابعة:

@Named("test")
public class TestComponent {
   ...
   @Inject public void setA(@TestQualifier String stringValue) {
   ...
   @Inject public void setB(@TestQualifier Integer integerValue) {

إنه يعمل فقط عندما يكون للطريقة إنشاء المنتج النوع المتوقع في توقيع الطريقة:

public class TestProducer {

  @Produces @SpringBean
  public String create(InjectionPoint ip) {

الآن تم حقن السلسلة بشكل صحيح ، لكن ليس لدي أي وسيلة لتوليد عدد صحيح من طريقة المنتج. ولكن هذا هو بالضبط ما أريد تجنبه ، لأن المنتج نفسه يجب أن يكون عامًا تمامًا.

هل أفعل شيئًا خاطئًا أم لا توجد طريقة لتحقيق السلوك الذي أريده؟

هل كانت مفيدة؟

المحلول

توضح جميع وثائق CDI أن CDI يفعل الأنواع حقن التبعية - وهي خاصية عاجلة لـ CDI. IMHO ، ما تحاول القيام به هو مجرد ما يحاول CDI تجنبه. تريد الحاوية لإلقاء Object لكل نوع و CDI لا يعمل بهذه الطريقة.

نقاط الحقن stringValue و integerValue لا يمكن سوى تلقي الفول الذي لديه java.lang.String و java.lang.Integer في قائمة أنواع الفول على التوالى. java.lang.Object لا يرضي هذا المعيار.

لدي اقتراحان. أولاً ، نظرًا لأن لديك نقطتين أو أكثر من الأنواع المختلفة ، قم بإنشاء طريقتين أو أكثر من المنتجين لتلك الأنواع:

public class TestProducer {

  @Produces @TestQualifier
  public String createString(InjectionPoint ip) {
    if(something) {
      return "a String";
    } else {
      // Some other value
    }
  }

  @Produces @TestQualifier
  public int createInt(InjectionPoint ip) {
    if(something) {
      return 42;
    } else {
      // Some other value
    }
  }
// ...

إنه يعمل إذا كان something الشرط هو مجرد التحقق من نوع نقطة الحقن (ما أراهن هو الحال).

ومع ذلك ، إذا كان something الشرط يقرر النوع باستخدام معايير أخرى غير نوع نقطة الحقن ، سأشير إلى القيام بـ "المهمة القذرة" بنفسك: حقن القيمة التي تم إرجاعها في Object-نقطة حقن مملوءة ويقوم المدلى بها يدويًا:

@Named("test")
public class TestComponent {
   ...
   @Inject public void setA(@TestQualifier Object value) {
       String stringValue = (String) value;

   ...
   @Inject public void setB(@TestQualifier Object value) {
       int intValue = (Integer) value;

النقطة الرئيسية هي أنه ، على عكس بعض أطر عمل DI الأخرى ، لا يعمل CDI مع نظام نوع Java - على العكس من ذلك ، فإنه يستخدمه بشدة. لا تحاول مكافحة ذلك ولكن استخدم هذا الجانب من CDI لصالحك :)

نصائح أخرى

منتج ل Object غريب على أي حال. لست متأكدًا مما إذا كان هذا ممنوعًا من خلال المواصفات ، أو أنه خطأ ، لكنني أعتقد أنه يمكنك جعل بعض الحلول الذكية:

public class ValueHolder<T> {
    private T value;

    public T getValue() {
        return value;
    }
}

ثم حقن أ ValueHolder<String> و ValueHolder<Integer>

من المحتمل إنشاء كائنات عامة مع CDI تنتج مثل ذلك:

  // the wrapper class
    public class Wrapper<T> {
      public final T bean;
      public Wrapper(T bean){
        this.bean = bean;
      }
    }

    // the producer inside some class
    @Produces
    public <T> Wrapper<T> create(InjectionPoint p){
      // with parameter 'p', it is possible retrieve the class type of <T>, at runtime
    }


    // the bean example 1
    public class BeanA {
      public void doFoo(){
        // ...
      }
    }
    // the bean example 2
    public class BeanB {
      public void doBar(){
        // ...
      }
    }


    // the class that uses the produced beans
    public class SomeBean{

//// There on producer method, do you can retrieve the Class object of BeanA and BeanB, from type parameters of Wrapper.

      @Inject
      private Wrapper<BeanA> containerA;
      @Inject
      private Wrapper<BeanB> containerB;

      public void doSomeThing(){
         containerA.doFoo();
         containerB.doBar();
      }

    }

يعمل على اللحام 2.2.0. أعتقد أن هذا يعمل على بعض الإصدارات السابقة أيضًا.

ستبحث أساليب التهيئة عن حبة مُدارة مع سلسلة أنواع API و integer ، ولكن طريقة المنتج الخاصة بك تحتوي فقط على نوع API (في حالة طريقة المنتج ، نوع الإرجاع).

وبالتالي ، يمكنك فقط استخدام الكائن في الحقول التي تم حقن طريقة التهيئة الخاصة بك ثم تمييز بين الأنواع من جسم المتلقي ، أو ببساطة لفها وطريقة المنتج في نوع فعلي يمكن الأدوية الجيلية)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top