spring
निर्भरता इंजेक्शन (DI) और नियंत्रण का उलटा (IoC)
खोज…
टिप्पणियों
बड़े सॉफ्टवेयर अनुप्रयोगों के लिए स्रोत कोड आमतौर पर कई इकाइयों में आयोजित किया जाता है। एक यूनिट की परिभाषा आमतौर पर इस्तेमाल की जाने वाली प्रोग्रामिंग भाषा द्वारा भिन्न होती है। उदाहरण के लिए, एक प्रक्रियात्मक प्रोग्रामिंग भाषा (जैसे सी) में लिखा गया कोड functions
या procedures
में व्यवस्थित होता है। इसी तरह, एक ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग लैंग्वेज (जैसे जावा, स्काला और सी #) में कोड classes
, interfaces
और इतने पर आयोजित किया जाता है। कोड संगठन की इन इकाइयों को समग्र सॉफ्टवेयर एप्लिकेशन बनाने वाली व्यक्तिगत इकाइयों के रूप में सोचा जा सकता है।
जब अनुप्रयोगों में कई इकाइयाँ होती हैं, तो उन इकाइयों के बीच अंतर-निर्भरताएँ बढ़ जाती हैं जब एक इकाई को अपनी कार्यक्षमता को पूरा करने के लिए दूसरों का उपयोग करना पड़ता है। निर्भर इकाइयों को consumers
और उन इकाइयों के रूप में सोचा जा सकता है जिन पर वे विशिष्ट कार्यक्षमता के providers
के रूप में निर्भर हैं।
उपभोक्ताओं के लिए सबसे आसान प्रोग्रामिंग दृष्टिकोण यह है कि कौन से प्रदाताओं को आवेदन के समग्र निष्पादन में किन बिंदुओं पर त्वरित, उपयोग और नष्ट किया जाना चाहिए, यह तय करके एक सॉफ्टवेयर एप्लिकेशन के प्रवाह को पूरी तरह से नियंत्रित करता है। उपभोक्ताओं को निष्पादन प्रवाह के दौरान प्रदाताओं पर पूर्ण नियंत्रण रखने के लिए कहा जाता है, जो उपभोक्ताओं के लिए dependencies
। यदि प्रदाताओं की अपनी निर्भरता होती है, तो उपभोक्ताओं को इस बारे में चिंता करनी पड़ सकती है कि प्रदाताओं को कैसे आरंभ किया जाए (और जारी किया जाए), जिससे नियंत्रण प्रवाह अधिक से अधिक जटिल हो जाए क्योंकि सॉफ्टवेयर में इकाइयों की संख्या बढ़ जाती है। यह दृष्टिकोण इकाइयों के बीच युग्मन को भी बढ़ाता है, जिससे सॉफ्टवेयर के अन्य भागों को तोड़ने की चिंता किए बिना इकाइयों को व्यक्तिगत रूप से बदलना मुश्किल हो जाता है।
इनवर्टर ऑफ़ कंट्रोल (IoC) एक डिज़ाइन-सिद्धांत है जो यूनिट डिस्कवरी, इंस्टेंटेशन और विनाश जैसी आउटसोर्सिंग नियंत्रण प्रवाह गतिविधियों की वकालत करता है, जो उपभोक्ताओं और प्रदाताओं से स्वतंत्र हैं। आईओसी के पीछे अंतर्निहित सिद्धांत उपभोक्ताओं और प्रदाताओं को अलग करना है, सॉफ्टवेयर इकाइयों को उनकी निर्भरता की खोज, त्वरित और सफाई की चिंता से मुक्त करने और इकाइयों को अपनी कार्यक्षमता पर ध्यान केंद्रित करने की अनुमति देना है। यह डीकॉउलिंग सॉफ्टवेयर को एक्स्टेंसिबल और मेंटेन रखने में मदद करता है।
निर्भरता इंजेक्शन नियंत्रण सिद्धांत को लागू करने के लिए तकनीकों में से एक है, जिसमें निर्भरता (प्रदाताओं) के उदाहरणों को एक सॉफ्टवेयर इकाई (उपभोक्ता) में इंजेक्ट किया जाता है, बजाय उपभोक्ता को खोजने और उन्हें तत्काल करने के लिए।
स्प्रिंग फ्रेमवर्क में एक कोर पर निर्भरता इंजेक्शन मॉड्यूल होता है जो स्प्रिंग-प्रबंधित बीन्स को अन्य स्प्रिंग-प्रबंधित बीन्स पर निर्भरता के रूप में इंजेक्ट करने की अनुमति देता है।
XML कॉन्फ़िगरेशन के माध्यम से मैन्युअल रूप से एक निर्भरता इंजेक्षन
निम्नलिखित जावा कक्षाओं पर विचार करें:
class Foo {
private Bar bar;
public void foo() {
bar.baz();
}
}
जैसा कि देखा जा सकता है, वर्ग Foo
को सफलतापूर्वक काम करने के लिए अपनी विधि foo
लिए एक अन्य वर्ग Bar
एक उदाहरण पर विधि baz
को कॉल करने की आवश्यकता है। Bar
को Foo
लिए एक निर्भरता कहा जाता है क्योंकि Foo
एक Bar
उदाहरण के बिना सही ढंग से काम नहीं कर सकता है।
कंस्ट्रक्टर इंजेक्शन
स्प्रिंग-प्रबंधित बीन्स को परिभाषित करने के लिए स्प्रिंग फ्रेमवर्क के लिए एक्सएमएल कॉन्फ़िगरेशन का उपयोग करते समय, प्रकार Foo
की एक सेम को निम्नानुसार कॉन्फ़िगर किया जा सकता है:
<bean class="Foo">
<constructor-arg>
<bean class="Bar" />
</constructor-arg>
</bean>
या, वैकल्पिक रूप से (अधिक क्रिया):
<bean id="bar" class="bar" />
<bean class="Foo">
<constructor-arg ref="bar" />
</bean>
दोनों मामलों में, स्प्रिंग फ्रेमवर्क पहले Bar
का एक उदाहरण बनाता है और इसे Foo
आवृत्ति में injects
करता है। यह उदाहरण मानता है कि क्लास Foo
में एक कंस्ट्रक्टर है जो एक पैरामीटर के रूप में Bar
उदाहरण ले सकता है, जो है:
class Foo {
private Bar bar;
public Foo(Bar bar) { this.bar = bar; }
}
इस शैली को कंस्ट्रक्टर इंजेक्शन के रूप में जाना जाता है क्योंकि निर्भरता ( Bar
उदाहरण) को क्लास कंस्ट्रक्टर के माध्यम से इंजेक्ट किया जा रहा है।
संपत्ति इंजेक्शन
Foo
में Bar
निर्भरता इंजेक्षन करने के लिए एक और विकल्प है:
<bean class="Foo">
<property name="bar">
<bean class="Bar" />
</property>
</bean>
या, वैकल्पिक रूप से (अधिक क्रिया):
<bean id="bar" class="bar" />
<bean class="Foo">
<property name="bar" ref="bar" />
</bean>
इसके लिए Foo
वर्ग को एक सेटर विधि की आवश्यकता होती है जो Bar
उदाहरण को स्वीकार करता है, जैसे:
class Foo {
private Bar bar;
public void setBar(Bar bar) { this.bar = bar; }
}
जावा कॉन्फ़िगरेशन के माध्यम से मैन्युअल रूप से एक निर्भरता इंजेक्षन
XML कॉन्फ़िगरेशन के साथ ऊपर दिखाए गए उदाहरणों को निम्नानुसार जावा कॉन्फ़िगरेशन के साथ फिर से लिखा जा सकता है।
कंस्ट्रक्टर इंजेक्शन
@Configuration
class AppConfig {
@Bean
public Bar bar() { return new Bar(); }
@Bean
public Foo foo() { return new Foo(bar()); }
}
संपत्ति इंजेक्शन
@Configuration
class AppConfig {
@Bean
public Bar bar() { return new Bar(); }
@Bean
public Foo foo() {
Foo foo = new Foo();
foo.setBar(bar());
return foo;
}
}
XML कॉन्फ़िगरेशन के माध्यम से एक निर्भरता को स्वचालित करना
वसंत ढांचे के घटक स्कैन सुविधा का उपयोग करते समय निर्भरता को कम किया जा सकता है। काम करने के लिए ऑटो-फायरिंग के लिए, निम्न XML कॉन्फ़िगरेशन बनाना होगा:
<context:annotation-config/>
<context:component-scan base-package="[base package]"/>
जहां, base-package
पूरी तरह से योग्य जावा पैकेज है, जिसके भीतर स्प्रिंग को घटक स्कैन करना चाहिए।
कंस्ट्रक्टर इंजेक्शन
आश्रितों को वर्ग निर्माता के माध्यम से इंजेक्ट किया जा सकता है:
@Component
class Bar { ... }
@Component
class Foo {
private Bar bar;
@Autowired
public Foo(Bar bar) { this.bar = bar; }
}
यहां, @Autowired
एक स्प्रिंग-विशिष्ट एनोटेशन है। अन्य जावा-आधारित निर्भरता इंजेक्शन फ्रेमवर्क में एप्लिकेशन पोर्टेबिलिटी को सक्षम करने के लिए स्प्रिंग JSR-299 का भी समर्थन करता है। इससे @Autowired
को @Inject
साथ प्रतिस्थापित किया जा सकता है:
@Component
class Foo {
private Bar bar;
@Inject
public Foo(Bar bar) { this.bar = bar; }
}
संपत्ति इंजेक्शन
निर्भरताएँ भी सेटर विधियों का उपयोग करके इंजेक्ट की जा सकती हैं:
@Component
class Foo {
private Bar bar;
@Autowired
public void setBar(Bar bar) { this.bar = bar; }
}
फील्ड इंजेक्शन
ऑटो-फायरिंग भी निम्न के रूप में सीधे वर्ग उदाहरणों के भीतर क्षेत्रों को आरंभ करने की अनुमति देता है:
@Component
class Foo {
@Autowired
private Bar bar;
}
स्प्रिंग संस्करण 4.1+ आप उपयोग कर सकते हैं वैकल्पिक वैकल्पिक निर्भरता के लिए।
@Component
class Foo {
@Autowired
private Optional<Bar> bar;
}
उसी दृष्टिकोण का उपयोग कंस्ट्रक्टर डि के लिए किया जा सकता है।
@Component
class Foo {
private Optional<Bar> bar;
@Autowired
Foo(Optional<Bar> bar) {
this.bar = bar;
}
}
जावा कॉन्फ़िगरेशन के माध्यम से एक निर्भरता को स्वचालित करना
जावा कॉन्फ़िगरेशन के माध्यम से कंस्ट्रक्टर इंजेक्शन भी ऑटोवेयरिंग का उपयोग कर सकता है, जैसे:
@Configuration
class AppConfig {
@Bean
public Bar bar() { return new Bar(); }
@Bean
public Foo foo(Bar bar) { return new Foo(bar); }
}