使用注释进行异常处理?

use*_*413 13 java annotations exception-handling exception try-catch

假设我有一种抛出某种异常的方法.抛出异常的代码位于访问外部服务的第三方库中.我有一些类可以完成外部服务的大量工作,并且在整个过程中有很多异常处理来处理潜在的问题.我遇到的问题是我可能有很多例外,但我可能只需要执行一些操作,如果有的话,并且有大量的try/catch块.异常的类型甚至可能不相关,或者不同的方法可能抛出相同类型的异常,但是根据抛出它的方法需要采取不同的操作.

我正在寻找的是一个注释,它可以取代try/catch,并简单地指示当该方法中存在异常时要采取的行为.我知道Spring ApsectJ可以做到这一点,但我现在无法轻松添加任何新的依赖项或修改pom来调整现有的依赖项.因此,我希望通过自定义注释可以实现这一点.例如:

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

当然,我会假设一个单独的类会处理异常.另一个困难是我需要传递的ServiceObj.如果makeThingsHappen()失败,我可能需要obj来执行其他操作.action变量将告诉处理程序类如何处理obj.

这可以在没有严重粪便的情况下完成,还是我希望有可能不存在的东西?

小智 27

这应该是一个低级别的过程,并不意味着我们不能在当前级别上拥有相同的东西,但它可能需要一堆代码并且会使系统复杂化一点.但是我的建议是这样的(我希望我弄错了),首先为谁想要处理异常定义一个接口,就像这样.

interface ExceptionHandler{
  void handleException(Throwable t);
}
Run Code Online (Sandbox Code Playgroud)

然后为用户(API)提供注释以标记其方法可能会抛出一些异常.

@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();
}
Run Code Online (Sandbox Code Playgroud)

接下来我们需要一个接口来开始调用可能抛出异常的方法,就像这样.

interface Caller{
  void callMethod()throws Throwable;
}
Run Code Online (Sandbox Code Playgroud)

那么你需要一个小心并管理执行流程并调用可能的异常处理程序的人

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;
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,让我们举一些例子,它对我来说效果很好,很酷.异常处理程序.

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());
  }
}
Run Code Online (Sandbox Code Playgroud)

和方法调用者.

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,用户通过该callmethod()方法调用方法,您还将省略该Caller接口,并使用注释在类中声明需要一堆额外codez的多个方法.我希望我能伸出援助之手.