2016-11-11 11 views
7

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

यदि ऑब्जेक्ट को डीआई फ्रेमवर्क द्वारा वसंत की तरह तत्काल किया गया था, तो फ्रेमवर्क सभी निर्भरताओं को तार देगा। अगर मैं मैन्युअल रूप से ऑब्जेक्ट्स को तुरंत चालू कर रहा था, तो मैं कन्स्ट्रक्टर पैरामीटर के माध्यम से निर्भरता प्रदान करता हूं। लेकिन जावाएफएक्स एप्लिकेशन में मैं क्या करूँ?

धन्यवाद!

उत्तर

11

आप FXMLLoader के लिए controller factory निर्दिष्ट कर सकते हैं। नियंत्रक फैक्ट्री एक ऐसा फ़ंक्शन है जो नियंत्रक वर्ग को ऑब्जेक्ट (संभवतः, लेकिन जरूरी नहीं, उस वर्ग का एक उदाहरण) पर मैप करता है जिसे नियंत्रक के रूप में उपयोग किया जाएगा।

ApplicationContext context = ... ; 

FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
loader.setControllerFactory(context::getBean); 
Parent root = loader.load(); 
SomeController controller = loader.getController(); // if you need it... 
// ... 

और अब FXMLLoadercontext.getBean(c); को फोन करके एक Class<?> c के लिए नियंत्रक उदाहरण बना देगा:

तो तुम स्प्रिंग आप के लिए नियंत्रक उदाहरणों बनाना चाहते हैं, इस के रूप में सरल हो सकता है।

public class SomeController { 

    // injected by FXMLLoader: 
    @FXML 
    private TextField someTextField ; 

    // Injected by Spring: 
    @Inject 
    private MyService service ; 

    public void initialize() { 
     someTextField.setText(service.getSomeText()); 
    } 

    // event handler: 
    @FXML 
    private void performAction(ActionEvent e) { 
     service.doAction(...); 
    } 
} 

साथ

@Configuration 
public class AppConfig { 

    @Bean 
    public MyService service() { 
     return new MyServiceImpl(); 
    } 

    @Bean 
    @Scope("prototype") 
    public SomeController someController() { 
     return new SomeController(); 
    } 

    // ... 
} 

आप एक डि ढांचे का उपयोग नहीं कर रहे हैं, और आप "हाथ से" इंजेक्शन क्या करना चाहते हैं:

तो, उदाहरण के लिए, आप एक विन्यास हो सकता था , आप ऐसा कर सकते हैं, लेकिन इसमें काफी प्रतिबिंब का उपयोग करना शामिल है। निम्नलिखित कैसे पता चलता है (और आप कितना कुरूप काम स्प्रिंग आप के लिए क्या कर रहा है की एक विचार दे देंगे!):

FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml")); 
MyService service = new MyServiceImpl(); 
loader.setControllerFactory((Class<?> type -> { 
    try { 
     // look for constructor taking MyService as a parameter 
     for (Constructor<?> c : type.getConstructors()) { 
      if (c.getParameterCount() == 1) { 
       if (c.getParameterTypes()[0]==MyService.class) { 
        return c.newInstance(service); 
       } 
      } 
     } 
     // didn't find appropriate constructor, just use default constructor: 
     return type.newInstance(); 
    } catch (Exception exc) { 
     throw new RuntimeException(exc); 
    } 
}); 
Parent root = loader.load(); 
// ... 

और फिर बस

public class SomeController { 

    private final MyService service ; 

    public SomeController(MyService service) { 
     this.service = service ; 
    } 

    // injected by FXMLLoader: 
    @FXML 
    private TextField someTextField ; 

    public void initialize() { 
     someTextField.setText(service.getSomeText()); 
    } 

    // event handler: 
    @FXML 
    private void performAction(ActionEvent e) { 
     service.doAction(...); 
    } 
} 

अंत में करते हैं, आप की जाँच करने के लिए चाहते हो सकता है afterburner.fx, जो कि बहुत हल्का है (सभी बेहतरीन तरीकों से) जावाएफएक्स-विशिष्ट डी ढांचे। (यह एक सम्मेलन-ओवर-कॉन्फ़िगरेशन दृष्टिकोण का उपयोग करता है, जहां आप केवल FXML फ़ाइल नामों को नियंत्रक वर्ग के नामों से मेल खाते हैं, और वैकल्पिक रूप से सीएसएस फ़ाइल नामों से मेल खाते हैं, और सबकुछ बस काम करता है।)

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