2011-02-11 18 views
28

FactoryBean प्रोग्रामेटिक रूप से ऐसी वस्तुओं को बनाने के लिए उपयोग किया जा सकता है जिन्हें जटिल तत्काल तर्क की आवश्यकता हो सकती है।फैक्टरीबीन वसंत द्वारा निर्मित बीन्स कैसे प्राप्त करें?

हालांकि, ऐसा लगता है कि FactoryBean द्वारा वसंत प्रबंधित नहीं किया गया है। क्या यह व्याख्या सही है? यदि हां, तो क्या कोई अच्छा कामकाज है? मेरी समस्या को स्पष्ट करने के लिए एक संक्षिप्त कोड नमूना शामिल किया गया है।

ApplicationContext:

<bean id="searcher" class="some.package.SearcherFactory" /> 
<bean id="service" class="some.package.Service" /> 

फैक्टरी कार्यान्वयन:

public class SearcherFactory implements FactoryBean<Searcher> { 

    @Override 
    public Searcher getObject() throws Exception { 
     return new Searcher(); // not so complex after all ;) 
    } 

    @Override 
    public Class<Searcher> getObjectType() { 
     return Searcher.class; 
    } 
    .... 
} 

कक्षा कारखाने के द्वारा बनाई गई:

public class Searcher() { 
     private Service service; 

     @Autowired 
     public void setService(Service service) { 
      // never invoked 
      this.service=service; 
     } 
} 

उत्तर

17

FactoryBeanद्वारा बनाई गई वस्तु स्प्रिंग द्वारा प्रबंधित की गई है, लेकिन वसंत द्वारा तत्काल या कॉन्फ़िगर नहीं किया गया है। FactoryBean का उपयोग करके, आप इसके लिए ज़िम्मेदारी लेते हैं। सभी इंजेक्शन और कॉन्फ़िगरेशन को FactoryBean

एक विकल्प है जो आपके लिए बेहतर काम कर सकता है - annotation-based config instead of XML-based config का उपयोग करें। इसका अर्थ यह है कि आप जावा में जटिल तत्काल तर्क कर सकते हैं, जबकि अभी भी वस्तुओं पर @Autowired जैसी चीजों का उपयोग कर सकते हैं।

मैं अब सभी गैर-तुच्छ स्प्रिंग ऐप्स के लिए एनोटेशन-स्टाइल कॉन्फ़िगरेशन का उपयोग करता हूं, यह कई चीजों को बहुत आसान बनाता है।

public abstract class AbstractAutowiringFactoryBean<T> extends 
    AbstractFactoryBean<T> implements ApplicationContextAware{ 

    private ApplicationContext applicationContext; 

    @Override 
    public void setApplicationContext(
     final ApplicationContext applicationContext){ 
     this.applicationContext = applicationContext; 
    } 

    @Override 
    protected final T createInstance() throws Exception{ 
     final T instance = doCreateInstance(); 
     if(instance != null){ 
      applicationContext 
       .getAutowireCapableBeanFactory() 
       .autowireBean(instance); 
     } 
     return instance; 
    } 

    /** 
    * Create the bean instance. 
    * 
    * @see #createInstance() 
    */ 
    protected abstract T doCreateInstance(); 

} 

, यह बढ़ाएँ getObjectType() और doCreateInstance() तरीकों को लागू करने और आप ऊपर और autowiring के साथ चल रहे हैं:

+0

+1। मैंने अभी इन प्रकार के परिदृश्यों से निपटने के लिए एनोटेशन आधारित कॉन्फ़िगरेशन के साथ काम करना शुरू कर दिया है। – Fil

+5

तो, आप समस्या लेखक को कैसे हल करेंगे? क्या आप उचित जावा कॉन्फ़िगरेशन के साथ एक उत्तर अपडेट कर सकते हैं? –

4

एक मैनुअल तरीका होगा:

  1. कारखाने बीन
  2. पर निर्भरता इंजेक्ट करें उन्हें लक्षित ऑब्जेक्ट पर मैन्युअल रूप से सेट करें।

तुम भी कारखाने सेम में ApplicationContext इंजेक्षन कर सकते हैं (या इसे ApplicationContextAware को लागू करने से मिलता है), और ctx.getAutowireCapableBeanFactory().autowireBean(bean)

मैं दोनों अजीब लग रहा है स्वीकार करते हैं, हालांकि है।

लेकिन वास्तव में, यदि तर्क सरल है (केवल तात्कालिकता), prototype स्कोप का उपयोग करें।

+0

यह काम करता है, और कम से कम वसंत युग्मन को एक कारखाने वर्ग में कम किया जा सकता है। –

-3

नहीं, FactoryBean द्वारा निर्मित बीन्स वसंत द्वारा भी प्रबंधित किए जाते हैं।

+7

यह उत्तर सिर्फ सादा भ्रामक है। यह गलत नहीं है, बीन प्रबंधित है, लेकिन बीन की निर्भरता नहीं है। –

27

यहाँ एक सार FactoryBean कार्यान्वयन है कि आप के लिए autowiring करता है।

नोट: बीनपोस्ट प्रोसेसर लागू नहीं हैं, जिसके लिए अतिरिक्त कोड की आवश्यकता होगी।

+1

यह या तो एक बुरा विचार नहीं है, या तो पुन: प्रयोज्यता में सुधार। हालांकि मुझे आश्चर्य है कि क्यों यह स्प्रिंगसोर्स पर हमारे दोस्तों द्वारा टेम्पलेट के रूप में पहले ही प्रदान नहीं किया गया था। –

17

इसके बारे में क्या?

<bean id="serviceFactory" 
     class="some.package.SearcherFactory" /> 


<bean id="service" 
     factory-bean="serviceFactory" 
     factory-method="getObject"/> 

... और फिर बस सेम 'सेवा' इंजेक्षन और अपने कोड

+0

ने इसे आजमाया, जिसके परिणामस्वरूप एक समस्या के साथ एक स्टैकट्रैक हुआ, कि getObject() विधि मौजूद नहीं है। इस लिंक के मुताबिक: http://goo.gl/V6NyLv एक service.getObject()। GetObject() को कॉल किया जाएगा। – Ev0oD

+0

टिप्पणीकर्ता का मतलब शाब्दिक रूप से ऊपर की प्रतिलिपि बनाने का मतलब नहीं है। इस मामले में आपके खोज फ़ैक्टरी प्रकार को getObject() जैसी विधि लागू करने की आवश्यकता है जो वांछित प्रकार की वस्तु को वापस कर देगी, या आप जो भी चाहें उस विधि को नाम दे सकते हैं। – Matunos

0

एक FactoryBean में कारखाने के बारे में परवाह नहीं है एक अंतरफलक है कि आप, एक डेवलपर के रूप में, लागू करता कारखाने कक्षाओं जब लेखन है और आप कारखाने वर्ग द्वारा स्प्रिंग द्वारा एक बीन के रूप में प्रबंधित करने के लिए बनाई गई वस्तु चाहते हैं, जबकि दूसरी ओर एक बीनफैक्टरी, स्प्रिंग आईओसी कंटेनर का प्रतिनिधित्व करती है, इसमें प्रबंधित सेम होते हैं और उन्हें पुनर्प्राप्त करने के लिए पहुंच प्रदान करते हैं। यह ढांचे के मूल का हिस्सा है जो नियंत्रण कंटेनर के विचलन की आधार कार्यक्षमता को लागू करता है।

ज्यादातर मामलों में आप सीधे बीनफ़ैक्टरी इंटरफ़ेस का उपयोग या कार्यान्वित नहीं करेंगे, जब तक आप ढांचे की मूल कार्यक्षमता को विस्तारित नहीं कर लेते। जबकि आप फैक्ट्रीबीन को लागू करेंगे, जब आपके पास ऐसी वस्तुएं होंगी जो कारखानों द्वारा बनाई गई हैं जिन्हें स्प्रिंग द्वारा प्रबंधित करने की आवश्यकता है।

अधिक संक्षिप्त शब्दों में, बीनफ़ैक्ट्री स्प्रिंग कंटेनर का प्रतिनिधित्व करता है जबकि फैक्ट्रीबीन कारखाने के वर्गों का प्रतिनिधित्व करता है जिनकी बनाई गई वस्तु को कंटेनर में एक बीन के रूप में उठाया जाता है और पंजीकृत किया जाता है।

File: context.xml 

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation=" 
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd"> 

    <bean id="sha" class="MessageDigestFactoryBean"> 
     <property name="algorithm" value="SHA1"/> 
    </bean> 

    <bean id="md5" class="MessageDigestFactoryBean"/> 

</beans> 


File: Main.java 

import java.security.MessageDigest; 

import org.springframework.beans.factory.FactoryBean; 
import org.springframework.beans.factory.InitializingBean; 
import org.springframework.beans.factory.xml.XmlBeanFactory; 
import org.springframework.core.io.ClassPathResource; 

public class Main { 
    public static void main(String[] args) { 
    XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml")); 
    String d1 = (String) factory.getBean("sha"); 
    String d2 = (String) factory.getBean("md5"); 
    System.out.println(d1); 
    System.out.println(d2); 
    } 

} 

class MessageDigestFactoryBean implements FactoryBean, InitializingBean { 
    private static final String DEFAULT_ALGORITHM = "MD5"; 

    private String algorithm = DEFAULT_ALGORITHM; 

    public Object getObject() throws Exception { 
    return this.algorithm; 
    } 

    public Class getObjectType() { 
    return MessageDigest.class; 
    } 

    public boolean isSingleton() { 
    return true; 
    } 

    public void setAlgorithm(String algorithm) { 
    this.algorithm = algorithm; 
    } 

    public void afterPropertiesSet() throws Exception { 
    this.algorithm += " after setting"; 
    } 
} 
संबंधित मुद्दे