वसंत में आत्म-तात्कालिक वस्तु में निर्भरता को कैसे इंजेक्ट करें?


128

मान लीजिए कि हमारे पास एक वर्ग है:

public class MyClass {
    @Autowired private AnotherBean anotherBean;
}

फिर हमने इस वर्ग का एक ऑब्जेक्ट बनाया (या कुछ अन्य ढांचे ने इस वर्ग का उदाहरण बनाया है)।

MyClass obj = new MyClass();

क्या अब भी आश्रितों को इंजेक्शन देना संभव है? कुछ इस तरह:

applicationContext.injectDependencies(obj);

(मुझे लगता है कि Google Guice में ऐसा कुछ है)

जवाबों:


194

की autowireBean()विधि का उपयोग करके आप ऐसा कर सकते हैं AutowireCapableBeanFactory। आप इसे एक मनमाना ऑब्जेक्ट पास करते हैं, और स्प्रिंग इसे अपने द्वारा बनाई गई चीज़ की तरह व्यवहार करेगा, और विभिन्न ऑटोवेयरिंग बिट्स और टुकड़ों को लागू करेगा।

पकड़ पाने के लिए AutowireCapableBeanFactory, बस यह स्वीकार करें:

private @Autowired AutowireCapableBeanFactory beanFactory;

public void doStuff() {
   MyBean obj = new MyBean();
   beanFactory.autowireBean(obj);
   // obj will now have its dependencies autowired.
}

अच्छा उत्तर (+1)। एक दूसरी विधि भी है जहाँ आप यह प्रभावित कर सकते हैं कि ऑटोवेयरिंग
सीन पैट्रिक फ्लोयड

लेकिन क्या होगा अगर मेरे पास दो वस्तुएं हैं, और पहली ऑटोवियर्स दूसरी है। मामले में निर्भरता के साथ ऑटोबायर बीन फैक्टरी कैसे व्यवहार करता है?
वादिम किरिलचुक

3
यह वास्तव में एक बुरा पैटर्न है। यदि यह है कि आप वास्तव में MyBean का उपयोग क्यों करते हैं तो बस पैरामीटर के रूप में एक और Bean के साथ कंस्ट्रक्टर क्यों नहीं है। कुछ इस तरह: codeनिजी @Autowired OtherBean सेम; public void doStuff () {MyBean obj = new MyBean (बीन); } code। ऐसा लगता है कि इन सभी एनोटेशन के साथ लोग वास्तव में भ्रमित हो जाते हैं और बस उस मूल पैटर्न का उपयोग नहीं करते हैं जो दिन 1 से जावा एसडीके में था। :(
डेनिस

3
मैं सहमत हूं - वसंत ने पूरी भाषा को फिर से परिभाषित किया है। अब हम इंटरफेस को कंक्रीट क्लास, क्लास इंस्टेंसेस के सभी तरीकों और जटिल और कोड के सभी तरीकों के रूप में उपयोग करते हैं जो आप नए और एक सभ्य डिजाइन के साथ करते थे।
रॉडनी पी। बारबाती

@Denis अगर MyBean की निर्भरता है कि वास्तविक वर्ग की आवश्यकता नहीं है, तो आप निर्भरता दर्ज कर रहे हैं जो वास्तव में मौजूद नहीं है, बस एक वर्ग को उदाहरण के लिए, इसलिए वास्तव में कोई अंतर नहीं है।
डाल्टन

17

आप अपने MyClass को @Configurable एनोटेशन के साथ भी चिह्नित कर सकते हैं:

@Configurable
public class MyClass {
   @Autowired private AnotherClass instance
}

फिर निर्माण के समय यह स्वचालित रूप से अपनी निर्भरता को इंजेक्ट करेगा। आपको <context:spring-configured/>अपने एप्लिकेशन संदर्भ xml में भी होना चाहिए ।


2
Galz666, जो मैं करना चाहता हूं, उसके लिए आपका तरीका बहुत साफ दिखता है। हालाँकि मुझे यह काम करने के लिए नहीं मिला। मेरे पास कोई xml फ़ाइल नहीं है और मैं पूरी तरह से जावा कॉन्फिगर का उपयोग कर रहा हूं। के बराबर है <context:spring-configured/>?
4

1
यह स्वच्छ समाधान है, लेकिन इसके लिए थोड़े अधिक प्रयास की आवश्यकता होती है: आपको या तो लोड-टाइम बुनाई का उपयोग करना चाहिए, जैसा कि iimuhin ऊपर दिखाता है या प्रोजेक्ट में AspectJ कंपाइलर जोड़ता है। लोड-टाइम जैसा कि नाम से पता चलता है कि रन-टाइम में अतिरिक्त लागत आएगी।
jsosnowski

4

बस एक ही जरूरत है और मेरे मामले में यह गैर स्प्रिंग प्रबंधनीय जावा वर्ग के अंदर पहले से ही तर्क था जिसकी पहुंच थी ApplicationContext। मचान से प्रेरित। द्वारा हल:

AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
factory.autowireBean(manuallyCreatedInstance);

3

मैं अपने समाधान है कि इस प्रकार साझा करना चाहते थे @Configurableदृष्टिकोण के रूप में briefly@ glaz666 में उल्लेख जवाब क्योंकि

  • जवाब @skaffman से करीब 10 साल पुराना है, और कहा कि अच्छा पर्याप्त नहीं मतलब यह नहीं है या काम नहीं करता
  • @ Glaz666 द्वारा उत्तर संक्षिप्त है और वास्तव में मेरी समस्या को हल करने में मेरी मदद नहीं की है, लेकिन मुझे सही दिशा में इंगित किया है

मेरा सेटअप

  1. स्प्रिंग बूट 2.0.3 के साथ Spring Neo4j & Aop starts(जो वैसे भी अप्रासंगिक है)
  2. दृष्टिकोण Spring Bootका उपयोग करते हुए तैयार होने पर बीन को तुरंत @Configurable(उपयोग करके ApplicationRunner)
  3. स्नातक और ग्रहण

कदम

मुझे काम करने के लिए नीचे दिए गए चरणों का पालन करने की आवश्यकता है

  1. @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false)अपने के शीर्ष पर रखा जा करने के लिए Beanहै कि मैन्युअल instantiated किया जाना है। मेरे मामले में Beanयह है कि मैन्युअल रूप से तत्काल किया जाना है @Autowiredसेवाओं है, इसलिए एनोटेशन के ऊपर सहारा।
  2. स्प्रिंग बूट के मुख्य एनोटेट XXXApplicaiton.java(उस के साथ टिप्पणी की जाती है या फ़ाइल @SpringBootApplicationके साथ) @EnableSpringConfiguredऔर@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
  3. अपनी बिल्ड फ़ाइल में निर्भरताएं जोड़ें (यानी build.gradle या pom.xml जिसके आधार पर आप उपयोग करते हैं) compile('org.springframework.boot:spring-boot-starter-aop')औरcompile('org.springframework:spring-aspects:5.0.7.RELEASE')
  4. आपका नया + Beanजो @Configurableकहीं भी एनोटेट किया गया है और उसकी निर्भरता को स्वत: समाप्त कर दिया जाना चाहिए।

* ऊपर # 3 बिंदु के संबंध में, मुझे पता है कि org.springframework.boot:spring-boot-starter-aopसकर्मक spring-aopरूप से (जैसा कि यहाँ mavencentral दिखाया गया है ) खींचता है , लेकिन, मेरे मामले में एक्लिप्स @EnableSpringConfiguredएनोटेशन को हल करने में विफल रहा, इसलिए, मैंने स्पष्ट रूप spring-aopसे स्टार्टर के अतिरिक्त निर्भरता को क्यों जोड़ा । क्या आपको एक ही मुद्दे का सामना करना चाहिए, बस निर्भरता की घोषणा करें या पता लगाने के रोमांच पर जाएं

  • वहाँ एक संस्करण संघर्ष है
  • क्यों org.springframework.context.annotation.aspect.*उपलब्ध नहीं है
  • क्या आपका आईडीई सेटअप ठीक है
  • आदि आदि।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.