2013-03-15 8 views
5

का उपयोग करके फ़ील्ड के प्रारंभिक मान को कैसे बदला जाए, मैं अपने विकासशील एनवी में कुछ सेवाओं का नकल करने की कोशिश कर रहा हूं।javassist

public class ApiFacadeImpl implements ApiFacade { 
private OneService oneService = null; 
    public OneService getOneService(){ 
     if(oneService==null) {//some initialization steps } 
     return oneService; 
    } 
} 

मैं इस कारखाने में अच्छी तरह से कोडित और नहीं बनाया गया है पता है: serviceFactory कोड कुछ की तरह है। हालांकि मैं इसके कोड को संशोधित नहीं कर सकता। मेरा विचार बाईटकोड को बदलने के लिए है, इसलिए मैं यह की तरह कुछ करने के लिए फिर से परिभाषित कर सकते हैं:

public class ApiFacadeImpl implements ApiFacade { 
private OneService oneService = new MyMockOneService(); 
    .... 
} 

मेरे 1st है: यह संभव javassist का उपयोग कर रहा है? और कैसे?

जब से मैं गूगल का उपयोग करते हुए javassist का उपयोग करके फ़ील्ड reinitialize की तरह कुछ भी नहीं मिल सकता है, मैं अपने आप को हटाकर उसे करने की कोशिश की और इसे पुन::

 CtField oneServiceField = cc.getDeclaredField("oneService"); 
    cc.removeField(oneServiceField); 
    CtField f = CtField.make(String.format("private %s %s=new %s();", 
      oneServiceField.getType().getName(), "oneService", 
      mockClass.getCanonicalName()), cc); 
    cc.addField(f); 
    cc.toClass(); 

तो मुझे मिल गया अपवाद:

javassist.CannotCompileException: by java.lang.ClassFormatError: Invalid length 99 in LocalVariableTable in class file com/Test 
at javassist.ClassPool.toClass(ClassPool.java:1051) 
at javassist.ClassPool.toClass(ClassPool.java:994) 
at javassist.ClassPool.toClass(ClassPool.java:952) 
at javassist.CtClass.toClass(CtClass.java:1079) 

मेरा दूसरा प्रश्न यह अपवाद क्यों है? कौन सा कदम अवज्ञा जावा वर्ग की परिभाषा?

public OneService getOneService(){ 
     if(oneService==null) {//some initialization steps } 
     return oneService; 
    } 

बहुत धन्यवाद: और जब मैं क्षेत्र को नष्ट javassist में क्षेत्र संदर्भ को नष्ट करने में मदद करता है।

+0

mockClass.getCanonicalName क्या है()? – longhua

+0

आपका जाववादी संस्करण क्या है? – longhua

उत्तर

4

प्रश्न # 1 के लिए, हाँ, आप इसे ApiFacadeImpl के निर्माता के माध्यम से संशोधित कर सकते हैं। असाइनमेंट कथन जोड़ने के लिए CtConstructor#insertAfter का उपयोग करना याद रखें।

ClassPool pool = ClassPool.getDefault(); 
CtClass factoryClass = pool.getCtClass("ServiceFactory"); 
CtConstructor constructor = factoryClass.getDeclaredConstructor(null); 
String setMockStatement = String.format("service = new %s();", 
     MockServiceImpl.class.getCanonicalName()); 
constructor.insertAfter(setMockStatement); 
factoryClass.toClass(); 
new ServiceFactory().getService().say(); 

मैंने आपके द्वारा प्रस्तावित तरीके की कोशिश की। हालांकि, यह काम नहीं किया। कुछ डिबगिंग के बाद, मैंने पाया कि यदि हम एक फ़ील्ड हटाते हैं, तो यह इस क्षेत्र के प्रारंभिक विवरण को नहीं हटाएगा। यदि हम अपने अपेक्षित प्रारंभिक विवरण के साथ फ़ील्ड को फिर से जोड़ते हैं, तो इसे मूल प्रारंभिक विवरण से पहले निष्पादित किया जाएगा। तो service फ़ील्ड को पहले MockServiceImpl पर असाइन किया गया है और फिर null पर असाइन किया गया है। कृपया निम्नलिखित जावासवादी बग देखें।

javassist-3.14.0-GA - Problm in default initializer of class variables when they are deleted and created using removeField and addField, CtField.make

प्रश्न # 2 के लिए, मुझे यकीन है कि ऐसा क्यों होता नहीं हूँ। आपका जाववादी संस्करण क्या है? आपका मॉक क्लास कैसा दिखता है? क्या आप निम्नलिखित जावासवादी बग का उल्लेख कर सकते हैं?

Javassist causes java.lang.ClassFormatError: Invalid length 561 in LocalVariableTable in class file

+0

लुहांग, उत्तर के लिए धन्यवाद। दरअसल मॉकक्लास सिर्फ वनसर्वस फैलाता है: पब्लिक क्लास मॉक क्लास वन सेवा {// कुछ भी नहीं} बढ़ाता है। मैं संदर्भ लिंक की जांच करूंगा। मैं javassist-3.11.0.GA बीटीडब्ल्यू का उपयोग करें। – kingpeter

+0

OneService एक इंटरफ़ेस या कक्षा है? – longhua

+0

OneService एक कक्षा है। – kingpeter

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