2013-10-15 8 views
8

मान लें कि मेरे पास एक तरीका है जो किसी प्रकार की अपवाद को फेंकता है। अपवाद-फेंकने वाला कोड किसी तृतीय-पक्ष लाइब्रेरी में स्थित है जो बाहरी सेवा तक पहुंचता है। मेरे पास कुछ कक्षाएं हैं जो बाहरी सेवाओं के साथ काम का एक अच्छा सौदा करती हैं और संभावित समस्याओं से निपटने के लिए पूरे अपवाद हैं। जिस मुद्दे पर मैं मार रहा हूं वह यह है कि मेरे पास बहुत सारे अपवाद हो सकते हैं, लेकिन अगर कोई है तो मुझे केवल कुछ कार्यों में से एक करने की आवश्यकता हो सकती है, और इसके बारे में कई बार कोशिश/पकड़ने वाले ब्लॉक हैं। अपवाद का प्रकार भी प्रासंगिक नहीं हो सकता है, या विभिन्न विधियां एक ही प्रकार के अपवाद को फेंक सकती हैं, लेकिन इसे फेंकने की विधि के आधार पर विभिन्न कार्रवाइयों को लेने की आवश्यकता है।अपवाद हैंडलिंग के लिए एनोटेशन का उपयोग करना?

जो मैं खोज रहा हूं वह एक एनोटेशन है जो उस विधि में अपवाद होने पर प्रयास करने/पकड़ने के लिए व्यवहार को आसानी से निर्देशित कर सकता है। मुझे पता है कि स्प्रिंग एपसेक्टजे इस तरह की चीज कर सकता है, लेकिन मैं वर्तमान में किसी भी नई निर्भरता को आसानी से जोड़ने या मौजूदा लोगों को समायोजित करने के लिए पोम को संशोधित करने में सक्षम नहीं हूं। इस प्रकार, मैं उम्मीद कर रहा हूं कि इसे एक कस्टम एनोटेशन के साथ पूरा किया जा सकता है। उदाहरण के लिए:

@Catcher(action=SomeEnum.SOME_ACTION) 
public void doSomething(ServiceObj obj) throws SomeException { 
    ExternalService.makeThingsHappen(obj); 
} 

मुझे लगता है कि एक अलग वर्ग अपवादों को संभालेगा। एक अतिरिक्त कठिनाई यह है कि मुझे सर्विसऑबज की भी आवश्यकता होगी जो कि पास हो चुकी है। यदि makeThingsHappen() विफल रहता है, तो मुझे अतिरिक्त क्रियाएं करने के लिए obj की आवश्यकता हो सकती है। एक्शन वैरिएबल हैंडलर क्लास को ओबीजे के साथ क्या करना है, बताएगा।

क्या यह गंभीर मकररी के बिना किया जा सकता है, या क्या मैं ऐसा कुछ उम्मीद कर रहा हूं जो अस्तित्व में न हो?

+0

एनोटेशन अपने आप में व्यवहार नहीं जोड़ते हैं। वे मेटाडेटा हैं। आपको उनके लिए एक पार्सर प्रदान करने की आवश्यकता है जो उस व्यवहार को जोड़ सकता है यदि वह उन्हें पाता है। –

+0

मैं इसे मामूली मकर कहूंगा; इसे एओपी या कुछ बाइट-कोड मैनिपुलेशन के साथ तुच्छ रूप से संभाला जा सकता है। –

उत्तर

17

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

interface ExceptionHandler{ 
    void handleException(Throwable t); 
} 

तो उपयोगकर्ता (एपीआई) के लिए एक टिप्पणी के अपने तरीकों चिह्नित करने के लिए उपलब्ध करा सकता है कुछ अपवाद फेंकता है।

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.ANNOTATION_TYPE) 
@interface Catch{ 
    public Class<? extends ExceptionHandler> targetCatchHandler(); 
    public Class<? extends Throwable> targetException() default Exception.class; 
} 


@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
@interface CatchGroup{ 
    public Catch[] catchers(); 
} 

अगले हम एक इंटरफेस की जरूरत विधि है जो हो सकता है अपवाद, कुछ इस तरह फेंकता कॉल करने के लिए शुरू करने के लिए।

interface Caller{ 
    void callMethod()throws Throwable; 
} 

तो आप एक पुरुष हैं, जो देखभाल और निष्पादन के प्रवाह का प्रबंधन और संभव अपवाद संचालक

class MethodCaller{ 
    /* 
    * @param isntance: instance which implemented the Caller interface 
    */ 
    public static void callMethod(Caller instance) 
     throws Exception { 
    Method m = instance.getClass().getMethod("callMethod"); 
    Annotation as[] = m.getAnnotations(); 
    Catch[] li = null; 
    for (Annotation a : as) { 
     if (a.annotationType().equals(CatchGroup.class)) { 
     li = ((CatchGroup) a).catchers(); 
     } 
     // for(Catch cx:li){cx.targetException().getName();} 
    } 
    try { 
     instance.callMethod(); 
    } catch (Throwable e) { 
     Class<?> ec = e.getClass(); 
     if (li == null) { 
     return; 
     } 
     for (Catch cx : li) { 
     if (cx.targetException().equals(ec)) { 
      ExceptionHandler h = cx.targetCatchHandler().newInstance(); 
      h.handleException(e); 
      break; 
     } 
     } 
    } 
    } 
} 

फोन और अंत में, चलो कुछ उदाहरण है की जरूरत है, यह मेरे लिए बहुत अच्छी तरह से काम करता है, यह शान्त है। अपवाद हैंडलर ।

public class Bar implements ExceptionHandler{//the class who handles the exception 
    @Override 
    public void handleException(Throwable t) { 
    System.out.println("Ta Ta"); 
    System.out.println(t.getMessage()); 
    } 
} 

और विधि कॉलर।

class Foo implements Caller{//the class who calls the method 
    @Override 
    @CatchGroup(catchers={ 
     @Catch(targetCatchHandler=Bar.class,targetException=ArithmeticException.class), 
     @Catch(targetCatchHandler=Bar.class,targetException=NullPointerException.class)}) 
    public void callMethod()throws Throwable { 
    int a=0,b=10; 
    System.out.println(b/a); 
    } 
    public static void main(String[] args) throws Exception { 
    Foo foo=new Foo(); 
    MethodCaller.callMethod(foo); 
    } 
} 

जैसा कि आप देख, उपयोगकर्ता callmethod() विधि द्वारा तरीकों फोन करना पड़ता है, तो आप भी Caller इंटरफेस छोड़ जाएगा, और एक वर्ग है कि यह अतिरिक्त के एक झुंड की जरूरत में एक से अधिक प्रणाली की घोषणा करने के लिए एनोटेशन का उपयोग codez। मुझे उम्मीद है कि मैं कुछ हाथ दे सकता हूं।

2

सहायता के लिए धन्यवाद, सब कुछ। मैंने स्प्रिंग एओपी में देखा, लेकिन आखिरकार इसके खिलाफ फैसला किया।मैं कोशिश/पकड़ ब्लॉक का उपयोग करके घायल हो गया, लेकिन एक हैंडलर तैयार करता हूं जिसे प्रत्येक वर्ग में इंजेक्शन दिया जाता है और मेरे अपवाद वर्ग में किसी भी फेंकने वाले अपवाद को लपेटता है, फिर उसे एक पंक्ति में हैंडलर में भेज दिया जाता है। यह user2511414 द्वारा सुझाव के समान ही है कि एक समर्पित हैंडलर है, लेकिन मैंने एनोटेशन पर छोड़ दिया। मेरे पास कोशिश/पकड़ ब्लॉक की एक अच्छी संख्या है, लेकिन कम से कम मैंने हैंडलिंग तर्क के बहुमत को रखा है। मामले में मेरी समाधान की एक त्वरित ठहरनेवाला अन्य लोगों इस लगता है, जो थोड़ा समझ से परे है, लेकिन आप अभी भी बात समझ सकते हैं:

public enum DoThisEnum { 
    DO_THIS, 
    DO_THAT, 
    DO_OTHER_THING; 
} 

public class MyException extends Exception { 

    private DoThisEnum doThis; 
    private MyObject dataObj; 

    //Constructor, overloaded to run super(originalException) or super() 
    //as well as taking doThis and dataObj as parameters 
    //Getters, setters, etc 
} 

public interface IExceptionHandler { 

    void handleException(MyException exception); 

} 

फिर एक ठोस वर्ग कि MyException लेता है साथ IExceptionHandler लागू, अतिरिक्त बाहर पढ़ता डेटा, और इसके आधार पर कार्रवाई करता है। फिर प्रत्येक ब्लॉक कि इस तरह के एक अपवाद फेंक सकती है तो तरह पकड़ा जा सकता है:

... 
try { 
    doSomething(Object data); 
} catch (SomeException e) { 
    handler.handleException(new MyException(e, DoThisEnum.DO_THAT, data)); 
    //Anything else to do, maybe return or return null, rethrow, etc. 
} 

अब बुनियादी तथ्य का सबसे हैंडलर में समझाया गया है और ट्राई/कैच ब्लॉक बहुत कम हैं। हैंडलर मूल अपवाद के स्टैक ट्रेस को लॉग कर सकता है, शायद इसके आधार पर अन्य चीजें करें, और फिर enum के आधार पर अपने स्वयं के कार्यों को निष्पादित करें। शायद यह सही समाधान नहीं है, लेकिन यह यहां काफी अच्छी तरह से काम करता है।

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