Java Academy · पाठ

कंस्ट्रक्टर इंजेक्शन और चक्रीय निर्भरताएँ

परीक्षण-योग्यता के लिए कंस्ट्रक्टर इंजेक्शन को प्राथमिकता दीजिए, चक्रीय निर्भरताएँ पहचानिए और @Lazy से उन्हें तोड़िए

पाठ 4, कुल 4 में से13 चरण

कंस्ट्रक्टर इंजेक्शन और चक्रीय निर्भरताएँ, CoddyKit पर Java Academy का एक निःशुल्क पाठ है। यह 4 में से 4वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह Java Academy सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। Java Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

इंजेक्शन के तीन प्रकार

स्प्रिंग कन्स्ट्रक्टर इंजेक्शन (अनुशंसित), फ़ील्ड इंजेक्शन (किसी फ़ील्ड पर @Autowired) और सेटर इंजेक्शन का समर्थन करता है। परीक्षणयोग्यता और अपरिवर्तनीयता के लिए कन्स्ट्रक्टर इंजेक्शन को प्राथमिकता दी जाती है।

कन्स्ट्रक्टर इंजेक्शन

निर्भरताओं को कन्स्ट्रक्टर पैरामीटर के रूप में घोषित करें। स्प्रिंग उन्हें अपने-आप इंजेक्ट करता है। यदि केवल एक कन्स्ट्रक्टर है, तो @Autowired वैकल्पिक है (Spring Boot 2.1+)।

@Service
public class OrderService {
    private final OrderRepository repo;
    private final EmailService email;
    // @Autowired is optional when there is only one constructor
    public OrderService(OrderRepository repo, EmailService email) {
        this.repo  = repo;
        this.email = email;
    }
}

कन्स्ट्रक्टर इंजेक्शन को प्राथमिकता क्यों दी जाती है

कन्स्ट्रक्टर इंजेक्शन: (1) निर्भरताएँ final होती हैं — यानी अपरिवर्तनीय, (2) क्लास हमेशा पूरी तरह आरंभित होती है, (3) इकाई परीक्षणों में स्प्रिंग की निर्भरता नहीं होती — केवल new OrderService(mockRepo, mockEmail) कॉल करें।

// Unit test — no Spring context needed:
OrderRepository mockRepo  = mock(OrderRepository.class);
EmailService    mockEmail = mock(EmailService.class);
OrderService    service   = new OrderService(mockRepo, mockEmail);
// Test service logic directly

फ़ील्ड इंजेक्शन (बचें)

@Autowired से फ़ील्ड इंजेक्शन संक्षिप्त है, लेकिन इसमें समस्याएँ हैं: फ़ील्ड को final नहीं बनाया जा सकता, निर्माण के बाद बीन पूरी तरह आरंभित नहीं होता, और इकाई परीक्षण के लिए स्प्रिंग या Mockito के रिफ्लेक्शन सहायक आवश्यक होते हैं।

// Avoid in production code:
@Service
public class UserService {
    @Autowired  // hidden dependency
    private UserRepository repo; // cannot be final
}

वैकल्पिक निर्भरताओं के लिए सेटर इंजेक्शन

ऐसी वैकल्पिक निर्भरताओं के लिए सेटर इंजेक्शन का उपयोग करें जिनका उचित डिफ़ॉल्ट मान हो — सेटर पर @Autowired(required = false) लगाएँ।

@Service
public class NotificationService {
    private SmsSender smsSender; // optional
    @Autowired(required = false)
    public void setSmsSender(SmsSender s) { this.smsSender = s; }
}

चक्रीय निर्भरता क्या है

चक्रीय निर्भरता तब होती है जब A को B की और B को A की आवश्यकता होती है (प्रत्यक्ष या अप्रत्यक्ष रूप से)। स्प्रिंग स्टार्टअप के समय इसका पता लगाता है और BeanCurrentlyInCreationException फेंकता है।

// CIRCULAR:
@Service class A { A(B b) {} }
@Service class B { B(A a) {} }
// Spring throws: BeanCurrentlyInCreationException: Is there an unresolvable circular reference?

चक्रीयता तोड़ना: तीसरी सेवा में पुनर्गठन

सबसे साफ़ समाधान यह है कि साझा तर्क को किसी तीसरी सेवा में निकाल लिया जाए, जिस पर न तो A और न ही B चक्रीय रूप से निर्भर हो।

// Before: A <-> B
// After: A -> C, B -> C (no cycle)
@Service class SharedLogic { ... }
@Service class A { A(SharedLogic s) {} }
@Service class B { B(SharedLogic s) {} }

चक्रीयता तोड़ना: @Lazy

किसी एक इंजेक्शन बिंदु पर @Lazy लगाएँ। स्प्रिंग तुरंत B के लिए एक प्रॉक्सी बनाता है; वास्तविक B का इंस्टेंस तभी बनाया जाता है जब A पहली बार उस पर कोई मेथड चलाता है।

@Service
public class A {
    private final B b;
    public A(@Lazy B b) { this.b = b; } // breaks the cycle
}

चक्रीयता तोड़ना: ApplicationContext से खोज

किसी एक बीन में ApplicationContext इंजेक्ट करें और context.getBean() के माध्यम से दूसरे बीन को विलंब से खोजें — लेकिन इससे परीक्षणयोग्यता और स्पष्टता कम हो जाती है।

@Service
public class A implements ApplicationContextAware {
    private ApplicationContext ctx;
    public void setApplicationContext(ApplicationContext c) { this.ctx = c; }
    public void doWork() { ctx.getBean(B.class).help(); }
}

चक्रीयता तोड़ने के लिए सेटर इंजेक्शन

सेटर-इंजेक्ट किए गए बीन पहले बनाए जाते हैं (निर्माण सफल होता है), फिर निर्भरताएँ सेट की जाती हैं। इससे परिवर्तनशीलता की कीमत पर चक्रीय निर्भरताएँ संभव हो जाती हैं।

@Service
public class A {
    private B b;
    @Autowired public void setB(B b) { this.b = b; } // Spring sets after construction
}

spring.main.allow-circular-references (Spring Boot 2.6+)

Spring Boot 2.6+ डिफ़ॉल्ट रूप से चक्रीय निर्भरताओं की अनुमति नहीं देता। पुनर्गठन करते समय केवल अस्थायी उपाय के रूप में इन्हें स्पष्ट रूप से सक्षम करें: spring.main.allow-circular-references=true।

# application.properties (temporary workaround only):
spring.main.allow-circular-references=true

त्वरित जाँच

फ़ील्ड इंजेक्शन की तुलना में कन्स्ट्रक्टर इंजेक्शन को प्राथमिकता क्यों दी जाती है?

पुनरावलोकन

कन्स्ट्रक्टर इंजेक्शन को प्राथमिकता दें: यह अपरिवर्तनीय, परीक्षण योग्य और स्पष्ट होता है। फ़ील्ड इंजेक्शन से बचें। चक्रीय निर्भरताएँ तोड़ने के लिए @Lazy का उपयोग करें या साझा सेवा निकालें। Spring Boot 2.6+ स्टार्टअप के समय चक्रीय संदर्भों को चिह्नित करता है — इन्हें डिज़ाइन संबंधी चेतावनियाँ मानें।

शुरुआत निःशुल्क

एआई शिक्षक के साथ Java सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
104
पाठ
374

अक्सर पूछे जाने वाले प्रश्न

क्या “कंस्ट्रक्टर इंजेक्शन और चक्रीय निर्भरताएँ” पाठ निःशुल्क है?

हाँ—“कंस्ट्रक्टर इंजेक्शन और चक्रीय निर्भरताएँ” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और Java Academy पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। Java Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“कंस्ट्रक्टर इंजेक्शन और चक्रीय निर्भरताएँ” में मैं क्या सीखूँगा?

परीक्षण-योग्यता के लिए कंस्ट्रक्टर इंजेक्शन को प्राथमिकता दीजिए, चक्रीय निर्भरताएँ पहचानिए और @Lazy से उन्हें तोड़िए आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ Java Academy का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या Java Academy शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर Java Academy शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 4वाँ पाठ है।

“कंस्ट्रक्टर इंजेक्शन और चक्रीय निर्भरताएँ” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस Java Academy पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर Java Academy पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. ऑटो-कॉन्फ़िगरेशन और Spring Boot स्टार्टर
  2. एप्लिकेशन प्रॉपर्टीज़ और प्रोफ़ाइल
  3. Bean वायरिंग: @Component, @Service, @Repository
  4. कंस्ट्रक्टर इंजेक्शन और चक्रीय निर्भरताएँ
← Java Academy पर वापस जाएँ