2014-10-16 73 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