2011-03-16 23 views
11

निम्नलिखित स्रोत कोड की तरह:मैं डेटाबेस से जावा क्लास कैसे लोड कर सकता हूं?

package util.abc; 
public class Test{ 
    public String out(){ 
     return "Hello World!"; 
    } 
} 

मैं का उपयोग कर सकते हैं:

Class c = Class.forName("util.abc.Test"); 

इस कक्षा प्राप्त करने के लिए, लेकिन मैं क्लासपाथ /util/abc/ में

मैं चाहता हूँ इस स्रोत फ़ाइल (Test.java) डाल करने के लिए करना चाहिए डेटाबेस से इस वर्ग को गतिशील लोड करें (स्रोत कोड को string, या binary) स्टोर करें

यह संभव है? मदद के लिए

धन्यवाद :)

+0

तो आप डेटाबेस में स्रोत (संकलित कक्षा नहीं) को स्टोर करना चाहते हैं, इसे फ्लाई पर संकलित करें, फिर इसे लोड करें? – justkt

+0

@justkt हाँ, क्या मैं कर सकता हूं? धन्यवाद :) – Koerr

उत्तर

21

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

public class DatabaseClassLoader extends ClassLoader { 

    public DatabaseClassLoader(ClassLoader parent, ... /* connection to database */) { 
     super(parent); 
     // store the connection 
    } 

    public Class findClass(String name) { 
     byte[] data = loadDataFromDatabase(name); 
     return defineClass(name, data, 0, data.length); 
    } 
    private byte[] loadDataFromDatabase(String name) { 
     // this is your job. 
    } 
} 

डेटाबेस केवल स्रोत कोड शामिल है, तो आपको पहले इसे संकलित करने के लिए होगा - कैसे किसी भी फाइल के बिना यह करने के लिए के लिए जावा एपीआई पर गौर।

ध्यान दें, इस प्रकार लोड किया गया वर्ग तब तक जीवित रहेगा जब तक कि क्लासलोडर जीवित रहता है, इसलिए आपको बदलाव के मामले में कक्षा को फिर से लोड करने में सक्षम होने के लिए एक नए वर्ग लोडर की आवश्यकता होगी।

इसके अलावा, यदि आप प्रतिबिंब के मुकाबले कक्षा के साथ अन्य तरीकों से बातचीत करना चाहते हैं, तो आप बेहतर कुछ इंटरफ़ेस (जो स्वयं अपने वर्ग पथ में हैं) को लागू करने दें, और एप्लिकेशन क्लास लोडर को अपने डेटाबेस के माता-पिता होने दें कक्षा लोडर।

आह, और लोड करने के लिए कैसे:

Class<?> c = Class.forName("util.abc.Test", myClassLoader); 

या सीधे

Class<?> c = myClassLoader.loadClass("util.abc.Test"); 

यहाँ एक तरीका है जिसके अपने इंटरफेस की वस्तुओं बनाता है (किसी भी इंटरफेस की, वास्तव में) है:

public <X> X getImplementingObject(Class<X> interfaceClass, String className) 
    throws ClassNotFoundException, IllegalAccessException, InstantiationException 
{ 
    ClassLoader loader = new DatabaseClassLoader(interfaceClass.getClassLoader(), ...); 
    Class<?> cl = loader.loadClass(className); 
    Class<? extends X> c = cl.asSubclass(interfaceClass); 
    return c.newInstance(); 
} 

(इसे सीएल की आवश्यकता है गधे को कोई तर्क नहीं है जो किसी भी अपवाद को फेंक नहीं देता है, बेशक (अगर ऐसा होता है, तो आपको यह अपवाद भी फेंक दिया जाएगा)।

यह इस तरह के प्रत्येक वर्ग के लिए एक नया क्लासलोडर बनाता है, इसलिए वे इंटरफ़ेस (या प्रतिबिंब) के माध्यम से केवल एक-दूसरे के साथ सहयोग कर सकते हैं।

ऑन-द-फ्लाई संकलन के लिए आपको जावा कंपाइलर एपीआई को देखना चाहिए, जैसा कि डीसीएन से उत्तर में उल्लिखित है। लेकिन मुझे लगता है कि पक्ष पर संकलन करना बेहतर होगा जो कक्षाओं को डेटाबेस में रखता है जो उन्हें खींचता है।

+0

धन्यवाद, मेरे उदाहरण के अनुसार, कोड पूरा हो सकता है? – Koerr

+0

@Zenofo: क्षमा करें, मैं आपके प्रश्न को समझ नहीं पा रहा हूं। आप क्या करना चाहते हैं? –

+0

मेरे पास एक इंटरफ़ेस है, और मैं इस इंटरफ़ेस द्वारा उपयोग की जाने वाली कई कक्षाओं को लागू करना चाहता हूं, इसलिए, किसी भी समय एक्सटेंशन को सुविधाजनक बनाने के लिए, मैं डेटाबेस में क्लास स्रोत को लागू करना चाहता हूं। – Koerr

5

यदि आप डीबी में स्रोत कोड स्टोर करना चाहते हैं, तो आप रनटाइम पर संकलित करने के लिए जावा 6 कंपाइलर एपीआई का उपयोग कर सकते हैं। उदाहरण के लिए here देखें।

रनटाइम पर कक्षाएं लोड करने के लिए, आप या तो URLClassLoader का उपयोग कर सकते हैं यदि आप किसी URL के साथ बाइटकोड का स्थान निर्दिष्ट कर सकते हैं या ClassLoader.defineClass का उपयोग कर सकते हैं और बाइट्स को बाइट्स की सरणी के रूप में आपूर्ति कर सकते हैं।

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

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

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