2013-11-03 7 views
6

में विधियों को अवरुद्ध करने में सक्षम नहीं है, हो सकता है कि मैं काफी कठिन सोच नहीं रहा हूं या उत्तर वास्तव में छिपी हुई है। त्वरित परिदृश्य (कोड को आज़माएं। यह संकलित करता है)।CGLIB सुपरक्लास/superinterface

एक विरासत इंटरफेस पर विचार करें

public interface LegacyInterfaceNoCodeAvailable{ 
    void logInfo(String message); 
} 

ऊपर

public abstract class LegacyClassNoCodeAvailable implements LegacyInterfaceNoCodeAvailable{ 

    public abstract void executeSomething(); 

    public void rockItOldSchool(){ 
     logInfo("bustin' chops, old-school style"); 
    } 

    @Override 
    public void logInfo(String message){ 
     System.out.println(message); 
    } 
} 

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

public class lass SpankingShiny extends LegacyClassNoCodeAvailable{ 

    public void executeSomething(){ 
     rockItOldSchool(); 
     logInfo("I'm the King around here now"); 
     System.out.println("this new stuff rocks!!"); 
    } 
} 

सब कुछ अच्छा काम करता है, केवल आपके उम्मीद करेंगे की तरह:

SpankingShiny shiny = new SpankingShiny(); 
shiny.executeSomething(); 

ऊपर कोड पैदावार (अपेक्षित रूप से):

bustin' chops, old-school style 
I'm the King around here now 
this new stuff rocks!! 

अब आप देख सकते हैं, 'सिस्टम। out.println() 'वांछित आउटपुट वांछित आउटपुट प्रिंट करता है। लेकिन मैं लॉगर के साथ 'System.out.println()' को प्रतिस्थापित करना चाहता हूं।

समस्या:

मैं 'logInfo (स्ट्रिंग)' के लिए विधि अवरोधन CGLIB प्रॉक्सी है करने में असमर्थ हूँ और यह एक लकड़हारा के माध्यम से बाहर मेरी वांछित संदेश मुद्रित है (मैं लॉगिंग विन्यास सही से किया है मार्ग)। उस विधि का आमंत्रण 'स्पष्ट रूप से' प्रॉक्सी नहीं मारा जाता है।

कोड:

public class SpankingShinyProxy implements MethodInterceptor{ 

    private SpankingShiny realShiny; 
    private final Logger logger = Logger.getLogger(SpankingShinyProxy.class); 

    public SpankingShinyProxy(SpankingShiny realShiny) { 
     super(); 
     this.realShiny = realShiny; 
    } 

    @Override 
    public Object intercept(Object proxyObj, Method proxyMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable { 
     String methodName = proxyMethod.getName(); 
     if("logInfo".equals(methodName)){ 
      logger.info(methodParams[0]); 
     } 
     return proxyMethod.invoke(realShiny, methodParams); 
    } 

    public static SpankingShiny createProxy(SpankingShiny realObj){ 
     Enhancer e = new Enhancer(); 
     e.setSuperclass(realObj.getClass()); 
     e.setCallback(new SpankingShinyProxy(realObj)); 
     SpankingShiny proxifiedObj = (SpankingShiny) e.create(); 
     return proxifiedObj; 
    } 
} 

मुख्य विधि:

public static void main(String... args) { 

     SpankingShiny shiny = new SpankingShiny(); 
     shiny.executeSomething(); 

     SpankingShiny shinyO = SpankingShinyProxy.createProxy(shiny); 
     shinyO.executeSomething(); 
    } 

ऊपर कोड पैदावार (नहीं के रूप में की उम्मीद):

bustin' chops, old-school style 
I'm the King around here now 
this new stuff rocks!! 
bustin' chops, old-school style 
I'm the King around here now 
this new stuff rocks!! 

कहाँ मैं गलत हो रहा होगा?

धन्यवाद!

उत्तर

1

ठीक है, सबसे पहले, आप भाग्यशाली हैं कि आपकी प्रॉक्सी हिट नहीं हुई है। यदि आप intercept के भीतर वास्तविक प्रॉक्सी का संदर्भ दे रहे थे, तो आप अंतहीन पाश के साथ समाप्त हो जाएंगे क्योंकि आपकी प्रतिबिंबित विधि अवशोषण उसी SpankingShinyProxy द्वारा प्रेषित किया जाएगा। बार बार।

प्रॉक्सी काम नहीं कर रहा है क्योंकि आप कुछ प्रॉप्रोक्सी ऑब्जेक्ट पर अपनी प्रॉक्सी पर विधि कॉल executeSomething को बस प्रतिनिधि करते हैं। आपको realObj का उपयोग नहीं करना चाहिए। सभी विधि कॉल को आपके प्रॉक्सी द्वारा प्रेषित किया जाना चाहिए, उन विधि कॉल जिन्हें भी प्रॉक्सी द्वारा मारा जाना चाहिए!

विधि में methodProxy.invokeSuper(proxyObj, args) पर अंतिम पंक्ति बदलें। फिर, Enhancer का उपयोग करके अपनी वस्तु का निर्माण करें। यदि SpankingShiny के लिए आपके कन्स्ट्रक्टर को तर्कों की आवश्यकता नहीं है, तो create पर कॉल किए बिना किसी भी तर्क के बिना कॉल करें। अन्यथा, उन वस्तुओं को आपूर्ति करें जिन्हें आप आम तौर पर create विधि में निर्माता को आपूर्ति करेंगे। फिर, केवल उस वस्तु का उपयोग करें जो आपको create से मिलता है और आप अच्छे हैं।

आप cglib बारे में अधिक जानकारी चाहते हैं, तो आप इस ब्लॉग लेख पढ़ने के लिए चाहते हो सकता है: http://mydailyjava.blogspot.no/2013/11/cglib-missing-manual.html

0

मैं एक ही समस्या थी। मेरे मामले में, realObj एक प्रॉक्सी स्वयं था (एक वसंत बीन - एक @Component)।

तो मुझे क्या करना था में .setSuperClass() भाग को बदल दिया गया था:

Enhancer e = new Enhancer(); 
e.setSuperclass(realObj.getClass()); 
e.setCallback(new SpankingShinyProxy(realObj)); 
SpankingShiny proxifiedObj = (SpankingShiny) e.create(); 

मैं बदल दिया है:

e.setSuperclass(realObj.getClass()); 

करने के लिए:

e.setSuperclass(realObj.getClass().getSuperClass()); 

यह काम किया, क्योंकि जैसा कि कहा, realObj.getClass() स्वयं एक CGLIB प्रॉक्सी था, और उस विधि ने एक पागल-नाम-CGLIB- जेनरेट किए गए क्लास लौटाए एस, जैसे a.b.c.MyClass$$EnhancerBySpringCGLIB$$1e18666c। जब मैंने .getSuperClass() जोड़ा, तो उसने कक्षा को वापस कर दिया जो इसे पहले स्थान पर लौटाना चाहिए था।

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