Using annotations for exception handling?

前端 未结 2 1225
滥情空心
滥情空心 2020-12-05 08:07

Let\'s say I have a method that throws an Exception of some kind. The exception-throwing code lies in a third-party library that access an external service. I have a few cla

2条回答
  •  广开言路
    2020-12-05 08:30

    This should be a low-level process, and it doesn't mean we cannot have the same thing with current level, but it may needs a bunch of code and would complex the system a little. However my suggestion would be like this(I hope I got it correct), first define an interface for who wants to process exceptions, something like this.

    interface ExceptionHandler{
      void handleException(Throwable t);
    }
    

    then provide an annotation for user(API) to mark its methods may throws some exception.

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    @interface Catch{
      public Class targetCatchHandler();
      public Class targetException() default Exception.class;
    }
    
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @interface CatchGroup{
      public Catch[] catchers();
    }
    

    next we need a interface to start to call the method which may throws exception, something like this.

    interface Caller{
      void callMethod()throws Throwable;
    }
    

    then you need a guy who take care and manage the flow of the execution and call the possible exception handler

    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;
            }
          }
        }
      }
    }
    

    and finally, lets have some example, it works very well for me, it's cool. the exception handler.

    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());
      }
    }
    

    and the method caller.

    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);
      }
    }
    

    as you see, the user HAS TO call the methods by the callmethod() method, you would also omit the Caller interface, and use annotation to declare more than one method in a class that it needs a bunch of extra codez. I hope I could give some hand.

提交回复
热议问题