使用注释进行exception处理?

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

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

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

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

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

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

 interface ExceptionHandler{ void handleException(Throwable t); } 

然后为用户(API)提供注释以标记其方法可能会抛出一些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(); } 

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

 interface Caller{ void callMethod()throws Throwable; } 

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

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

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

 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的多个方法。 我希望我能伸出援助之手。

感谢所有人的帮助。 我调查了Spring AOP,但最终决定反对它。 我使用了try / catch块,但是创建了一个处理程序,它被注入到每个类中并在我自己的exception类中包装任何抛出的exception,然后将它传递给一行中的处理程序。 这有点类似于user2511414的建议,因为有一个专用的处理程序,但我放弃了注释。 我有很多try / catch块,但至少我保留了大部分处理逻辑。 快速了解我的解决方案,以防其他人发现这一点,这有点混淆,但你仍然可以得到重点:

 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,读取其他数据,并基于它执行操作。 然后可以像这样捕获每个可能抛出这种exception的块:

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

现在大部分的细节被封装在处理程序中,而try / catch块是最小的。 处理程序可以记录原始exception的堆栈跟踪,也可以根据它执行其他操作,然后根据枚举执行自己的操作。 也许它不是完美的解决方案,但它在这里运作良好。