2014-10-16 76 views
5

我有以下的Groovy類:Groovy'with'closure重複嘗試catch塊?

@Slf4j 
class WidgetService { 
    WidgetDao widgetDao = new WidgetDao() 

    createWidget(String name, int type) { 
     try { 
      widgetDao.createWidget(name, type) 
     } catch(WidgetException wexc) { 
      log.error(wexc) 
      int x = doFizz() 
      long y = doBuzz(x) 
      determineHowToHandle(y) 
     } 
    } 

    Widget getWidgetById(Long id) { 
     try { 
      widgetDao.getWidgetById(id) 
     } catch(WidgetException wexc) { 
      log.error(wexc) 
      int x = doFizz() 
      long y = doBuzz(x) 
      determineHowToHandle(y) 
     } 
    } 

    Widget getWidgetByName(String name) { 
     try { 
      widgetDao.getWidgetByName(name) 
     } catch(WidgetException wexc) { 
      log.error(wexc) 
      int x = doFizz() 
      long y = doBuzz(x) 
      determineHowToHandle(y) 
     } 
    } 

    def deleteWidget(Widget w) { 
     try { 
      widgetDao.deleteWidget(w) 
     } catch(WidgetException wexc) { 
      log.error(wexc) 
      int x = doFizz() 
      long y = doBuzz(x) 
      determineHowToHandle(y) 
     } 
    } 

    ...dozens of more methods with *exact* same catch block 
} 

正如你可以看到我有很多重複的,樣板代碼在我的try-catch塊。這將是很好,如果我可以定義一個封閉或某種基於AOP的處理程序只是通過widgetDao方法的興趣到關閉/處理程序作爲一個lambda或類似的東西:

def createWidgetClosure = { it => 
    widgetDao.createWidget(it.name, it.type) 
} 

def getWidgetByIdClosure = { it => 
    widgetDao.getWidgetById(it.id) 
} 

def tryCatchClosure = { closure => 
    try { 
     closure() 
    } catch(WidgetException wexc) { 
     log.error(wexc) 
     int x = doFizz() 
     long y = doBuzz(x) 
     determineHowToHandle(y) 
    } 
} 

所以,我的` WidgetService可能會看起來像這樣:

@Slf4j 
class WidgetService { 
    WidgetDao widgetDao = new WidgetDao() 

    createWidget(String name, int type) { 
     tryCatchClosure(createWidgetClosure()) 
    } 

    Widget getWidgetById(Long id) { 
     tryCatchClosure(getWidgetByIdClosure()) 
    } 

    ...dozens of more methods with *exact* same catch block 
} 

這可能嗎?如果是這樣,怎麼樣?

回答

5

您可以簡單地通過使用tryCatchClosure來執行下面的操作。你甚至可以製作tryCatchClosure一種以Closure作爲參數的方法。

class WidgetService { 
    WidgetDao widgetDao = new WidgetDao() 

    def tryCatchClosure(Closure closure) { 
     try { 
      closure() 
     } catch(WidgetException wexc) { 
      log.error(wexc) 
      int x = doFizz() 
      long y = doBuzz(x) 
      determineHowToHandle(y) 
     } 
    } 

    createWidget(String name, int type) { 
     tryCatchClosure { 
      widgetDao.createWidget(name, type) 
     } 
    } 

    Widget getWidgetById(Long id) { 
     tryCatchClosure { 
      widgetDao.getWidgetById(id) 
     } 
    } 

    Widget getWidgetByName(String name) { 
     tryCatchClosure { 
      widgetDao.getWidgetByName(name) 
     } 
    } 

    def deleteWidget(Widget w) { 
     tryCatchClosure { 
      widgetDao.deleteWidget(w) 
     } 
    } 

    // ...dozens of more methods with *exact* same catch block 
} 

或者您也可以通過覆蓋其上的metaClass invokeMethod方法攔截上WidgetDao每個方法調用和處理異常(try/catch語句)。 Similar to this

+2

和'@ Delegate'一起歸結爲一個oneliner和一些錯誤處理代碼。必須愛groovy – cfrick 2014-10-16 15:18:10

+0

謝謝@cfrick(+1) - 你能解釋一下'@ Delegate'的意思嗎?也許提供一個代碼示例? – smeeb 2014-10-16 15:25:03

+3

@smeeb https://gist.github.com/christoph-frick/448ae72f38e771fc67b5 – cfrick 2014-10-16 15:25:28