2010-01-07 9 views
13

मैं सार्वजनिक फ़ील्ड के साथ निजी फ़ील्ड के साथ निर्भरता इंजेक्शन का उपयोग करके कई जावा उदाहरण देखता हूं:निजी, पैकेज या सार्वजनिक क्षेत्र में इंजेक्ट करें या एक सेटर प्रदान करें?

public SomeClass { 
    @Inject 
    private SomeResource resource; 
} 

लेकिन यह एक बुरा विचार है जब इंजेक्शन मैन्युअल रूप से यूनिट परीक्षणों में उदाहरण के लिए किया जाना चाहिए।

इसे हल करने के लिए कई संभावनाएं हैं:

  • एक सार्वजनिक सेटर जोड़ें: setSomeResource(SomeResource r)
  • फ़ील्ड को सार्वजनिक करें
  • फ़ील्ड पैकेज को संरक्षित करें

मैं चाहूंगा सेटर से बचें, क्योंकि इसमें वास्तव में कुछ भी नहीं होता है। तो मैं सार्वजनिक या पैकेज संरक्षित पसंद करेंगे। आप क्या सलाह देते हैं?

+0

http://stackoverflow.com/q/20270391/975169 Mockito – Sllouyssgort

उत्तर

7

मैं सेटर पसंद करते हैं

  • यह डिबग करने के लिए आसान है (एक सेटर में के बजाय क्षेत्र पहुँच/संशोधन पर एक ब्रेकपाइंट डाल)
  • आसान
  • आसान कुछ सत्यापन जोड़ने के लिए लॉग इन करने के (हालांकि यह हमेशा सबसे अच्छी जगह)
  • आसान द्विदिश रखरखाव का समर्थन करने के (हालांकि आईओसी कंटेनर से यह ठीक हो सकता है) नहीं है
  • किसी अन्य "मैन्युअल AOP" उद्देश्य
  • +०१२३५१६४१०

लेकिन वह सिर्फ मेरी राय

+0

साथ स्वत: इंजेक्शन ये अच्छा तर्क हैं। मैं अब सेटर या कन्स्ट्रक्टर इंजेक्शन (ईजेबी 3.1 के बाद से उपलब्ध) का उपयोग करूंगा। – deamon

+4

ऑब्जेक्ट को व्यवहार्य बना देगा जो एक समस्या हो सकती है – willcodejavaforfood

4

मैं सेटटर का उपयोग करने की सलाह देता हूं। this question में गेटर्स और सेटर्स का उपयोग करने के लाभ हैं।

12

एक तरह से क्षेत्र के लिए एक सेटर बनाने निर्माता इंजेक्शन का उपयोग कर रहा से बचने के लिए है। यह आपको फ़ील्ड को अंतिम रूप में घोषित करने की अनुमति देता है।

यह इस प्रकार है:

public class SomeClass { 
    private final SomeResource resource; 

    @Inject 
    public SomeClass(SomeResource resource) { 
     this.resource = resource; 
    } 
} 
7

जोड़ना setters, सर्वोत्कृष्ट समाधान नहीं है जब से तुम उत्पादन कोड है जो की जरूरत नहीं है जोड़ रहे हैं। हालांकि, प्रतिबिंब setters जोड़ने से एक भी बदतर समाधान है:

एक वैकल्पिक, http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html

संपादित करें (2017) को देखने के प्रतिबिंब का उपयोग कर अपने परीक्षण निर्भरता सुई वसंत के ReflectionTestUtils वर्ग का प्रयोग है। इस गड़बड़ी का कारण यह तथ्य है कि वसंत सेटर्स या कन्स्ट्रक्टर के बिना मूल्यों को इंजेक्ट करना संभव बनाता है। मेरा वर्तमान रुख उन में से किसी एक का उपयोग करने के लिए चिपकना है और काले जादू इंजेक्शन प्रथाओं का उपयोग करने से बचने के लिए है।

3
मेरी (यह एक से संबंधित) सवाल का जवाब की मदद से

:

How do app servers inject into private fields?

मैं कैसे setters बिना सुई पर इस सरल उदाहरण कोडित।

------- fields : -------- 
-> private int MyClass.theValue 
     found annotation: @Inject() 
     injecting ! 
23 
+0

सुझाव के लिए धन्यवाद। आप जेएसआर 330 से @ इंजेक्ट का उपयोग कर सकते हैं। – deamon

0

क्षेत्र आधारित इंजेक्शन के साथ, आप इस मुद्दे को परीक्षण का वर्णन में चलाने: शायद यह

//...................................................... 
import java.lang.annotation.*; 
import java.lang.reflect.*; 

//...................................................... 
@Target(value = {ElementType.FIELD}) 
@Retention(RetentionPolicy.RUNTIME) 
@interface Inject { 
} 

//...................................................... 
class MyClass { 

    @Inject 
    private int theValue = 0; 

    public int getTheValue() { 
     return theValue; 
    } 
} // class 

//...................................................... 
public class Example { 

    //...................................................... 
    private static void doTheInjection(MyClass u, int value) throws IllegalAccessException { 

     Field[] camps = u.getClass().getDeclaredFields(); 

     System.out.println("------- fields : --------"); 
     for (Field f : camps) { 
      System.out.println(" -> " + f.toString()); 
      Annotation an = f.getAnnotation(Inject.class); 
      if (an != null) { 
       System.out.println("  found annotation: " + an.toString()); 
       System.out.println("  injecting !"); 
       f.setAccessible(true); 
       f.set(u, value); 
       f.setAccessible(false); 
      } 
     } 

    } //() 

    //...................................................... 
    public static void main(String[] args) throws Exception { 

     MyClass u = new MyClass(); 

     doTheInjection(u, 23); 

     System.out.println(u.getTheValue()); 

    } // main() 
} // class 

भागो उत्पादन में मदद करता है। सेटर आधारित इंजेक्शन के साथ, यदि आप कुछ निर्भरताओं को सेट करना भूल जाते हैं तो परीक्षण चलाने पर एक अपूर्ण स्थिति में एक वर्ग का एक उदाहरण बनाया जा सकता है। मैं हाल ही में इस तथ्य के कारण कन्स्ट्रक्टर इंजेक्शन का अभ्यास कर रहा हूं कि जब भी आप परीक्षण के दौरान कक्षा का उदाहरण बनाते हैं तो यह आपको सभी निर्भरताओं को सेट करने के लिए मजबूर करता है। एंड्रॉइड रॉड्रिग्स द्वारा उपरोक्त उत्तर बताता है कि यह कैसे पूरा किया जाएगा। यह करने के लिए

0

संभावित समाधान:

  • JGlue CDI-Unit की तरह एक CDI-अवगत परीक्षण ढांचे का प्रयोग करें। इस तरह आपको कोई सेटर की आवश्यकता नहीं है। आप केवल अपने परीक्षणों के भीतर निर्भरता को परिभाषित करते हैं - आमतौर पर एक मॉकिटो मॉक ऑब्जेक्ट का उपयोग करते हैं। आईएमएचओ यह सबसे अच्छा समाधान है, क्योंकि आपको परीक्षण के लिए अतिरिक्त कुछ करने की आवश्यकता नहीं है।

  • कन्स्ट्रक्टर या सेटर में इंजेक्ट करें। यह सही है, आप सेटर्स में इंजेक्ट कर सकते हैं! More details here.

  • संरक्षित सेटटर का उपयोग करें। सरल और हर मामले में काम करता है। चूंकि यह संरक्षित है, इसलिए आप इसे अपने टेस्ट क्लास से एक्सेस कर सकते हैं (जिसमें आपकी परीक्षण कक्षा के समान पैकेज परिभाषा होनी चाहिए), और कोई अन्य पैकेज इसे एक्सेस नहीं कर सकता है।

  • एक गेटर का उपयोग करें और परीक्षण करते समय इसे ओवरराइड करें। अपनी टेस्ट क्लास में, एक नई आंतरिक कक्षा बनाएं जो परीक्षण कक्षा को बढ़ाती है और गेटर को ओवरराइड करती है। हालांकि, इसका एक बड़ा नुकसान है: आपकी टेस्ट क्लास को मैदान के बजाय आंतरिक रूप से गेटर का उपयोग करना पड़ता है। संभावित bugged बॉयलरप्लेट बहुत से ...

संबंधित मुद्दे