2012-11-06 20 views
17

के साथ सेवाएं मैं एक प्लगइन मॉड्यूल बनाना चाहता था जिसे ServiceLoader से लोड किया जा सकता है। इसके लिए META-INF/services निर्देशिका में फ़ाइल जोड़ने की आवश्यकता है, जिसका नाम सेवा इंटरफ़ेस के नाम पर रखा गया है और इसमें उस वर्ग के योग्यता पथ शामिल हैं जो इसे लागू करता है। फिर आप ServiceLoader.load() पर कॉल करके इन सेवाओं को लोड कर सकते हैं।मेटा-आईएनएफ/जीएआर में मेटल

हम org.example.plugins.PluginService नामक एक प्लगइन इंटरफ़ेस प्रदान करना चाहते हैं कहते हैं:

यहाँ एक उदाहरण है। इसके बाद हम कक्षा org.example.plugins.impl.ExamplePlugin कक्षा में इस सेवा का कार्यान्वयन प्रदान करते हैं।

अगर हम कुछ प्रकार की प्लगइन तंत्र चाहते हैं, तो हम एक जेएआर फ़ाइल बना सकते हैं, जिसमें कार्यान्वयन शामिल है। इस JAR फ़ाइल में फ़ाइल META-INF/services/org.example.plugins.PluginService भी होनी चाहिए। इस फ़ाइल में कार्यान्वयन को खोजने के लिए ServiceLoader सक्षम करने के लिए एक पंक्ति

org.example.plugins.impl.ExamplePlugin 

शामिल होना चाहिए। कि JAR फ़ाइल का निर्माण पथ में है, तो आप

Iterator<PluginService> it = ServiceLoader.load(PluginService.class).iterator(); 

कि इटरेटर कॉल करते समय भी सभी प्लग इन कि ServiceLoader से पाए जाते हैं पहुँच प्रदान करेगा द्वारा प्लगइन लोड कर सकते हैं।

किसी कारण से ग्रैडल में फ़ाइलों को META-INF निर्देशिका में डिफ़ॉल्ट रूप से शामिल नहीं किया गया है। परिणामस्वरूप जेएआर को ऐसी फाइल रखने का कोई तरीका है?

मुझे कक्षा Jar में पहले से ही metaInf विधि मिली है। लेकिन मुझे अपने आप को हल करने के लिए पर्याप्त अच्छा नहीं पता है।

+1

क्या आप निश्चित हैं? मेरे लिए ठीक काम करता है। आप इस फ़ाइल को कहां रखते हैं और आपका 'build.gradle' कैसे दिखता है? – axtavt

+0

मुख्य स्रोत फ़ोल्डर 'src/main/java' में' मेटा-आईएनएफ 'निर्देशिका है। बिल्ड स्क्रिप्ट के साथ कुछ खास नहीं है। यह लगभग एक मानक है, जिसमें कुछ अतिरिक्त निर्भरताएं और कुछ कस्टम भंडार शामिल हैं। – pvorb

उत्तर

28

आप src/main/java में META-INF/services/org.example.plugins.PluginService जगह लग रहा है, लेकिन यह एक स्रोत नहीं है, यह एक है संसाधन फ़ाइल, इसलिए इसे मैवेन निर्देशिका लेआउट सम्मेलन के अनुसार संसाधन फ़ोल्डर में रखा जाना चाहिए, जो

है
src/main/resources/META-INF/services/org.example.plugins.PluginService 

इस मामले में सब कुछ बॉक्स से बाहर काम करना चाहिए।

5

इस बीच मुझे अपनी समस्या का समाधान (कुछ हद तक) similar Question में मिला।

gradle.build फ़ाइल में निम्नलिखित जोड़ना, निराकरण मेरी समस्या

jar { 
    from ('./src/main/java') { 
    include 'META-INF/services/org.example.plugins.PluginService' 
    } 
} 

अब JAR फ़ाइल के रूप में की उम्मीद

. 
|- org 
| `- example 
|  `- plugins 
|  `- impl 
|   `- ExamplePlugin.class 
`- META-INF 
    |- MANIFEST.MF 
    `- services 
     `- org.example.plugins.PluginService 
+0

मैं अभी अपना जवाब स्वीकार नहीं करूंगा, क्योंकि मुझे लगता है कि यह केवल एक कामकाज है। उपरोक्त वर्णित @axtavt की तरह, इसे 'build.gradle' में इन पंक्तियों के बिना काम करना चाहिए। – pvorb

0

यदि आप कुछ चींटी आधारित विरासत कोड का उत्तराधिकारी होते हैं जो मैवेन सम्मेलनों का पालन नहीं करता है, तो निम्नलिखित मदद कर सकते हैं।

परिभाषित करें अपने स्रोत विरासत संरचना से मेल करने के लिए सेट है, और इस तरह की एक पंक्ति में शामिल हैं:

include 'META-INF/services/**'

अपने स्रोत सेट में। यह पैटर्न सामान्य है और आपकी सभी मेटा इंफ सेवाओं को उठाएगा।

नीचे पूरा उदाहरण।

sourceSets { 
    main { 
     java { 
      srcDir 'src' 
      exclude '**/Test*.java' 
     } 
     resources { 
      srcDir 'src' 
      include '**/*.xml' 
      include 'META-INF/services/**' 
     } 
    } 
    test { 
     java { 
      srcDir 'src' 
      include '**/Test*.java' 

     } 
     resources { srcDir 'resources' } 
    } 
}