用于包装方法的Java注释

我有很多样板代码基本上遵循这种模式:

function doSomething() { try { [implementation] [implementation] [implementation] [implementation] } catch (Exception e) { MyEnv.getLogger().log(e); } finally { genericCleanUpMethod(); } } 

我想创建自己的注释来清理我的代码:

 @TryCatchWithLoggingAndCleanUp function doSomething() { [implementation] [implementation] [implementation] [implementation] } 

方法签名变化很大(取决于方法的实际实现),但样板try / catch / finally部分始终相同。

我想到的注释将自动包装带注释方法的内容与整个try...catch...finally hoopla。

我一直在寻找一种直截了当的方法,但却没有找到任何东西。 我不知道,也许我只是看不到所有注释树木的树林。

关于如何实现这样的注释的任何指针都将非常感激。

要做到这一点,你需要一些在你的方法周围使用代理的AOP框架。 此代理将捕获exception并执行finally块。 坦率地说,如果你不使用支持AOP的框架,我不确定我会用一个只是保存这几行代码。

您可以使用以下模式以更优雅的方式执行此操作:

 public void doSomething() { logAndCleanup(new Callable() { public Void call() throws Exception { implementationOfDoSomething(); return null; } }); } private void logAndCleanup(Callable callable) { try { callable.call(); } catch (Exception e) { MyEnv.getLogger().log(e); } finally { genericCleanUpMethod(); } } 

我只使用Callable作为接口,但您可以定义自己的Command接口:

 public interface Command { public void execute() throws Exception; } 

因此,无需使用通用的Callable并从Callable返回null。

编辑:如果你想从你的方法返回一些东西,那么使logAndCleanup()方法通用。 这是一个完整的例子:

 public class ExceptionHandling { public String doSomething(final boolean throwException) { return logAndCleanup(new Callable() { public String call() throws Exception { if (throwException) { throw new Exception("you asked for it"); } return "hello"; } }); } public Integer doSomethingElse() { return logAndCleanup(new Callable() { public Integer call() throws Exception { return 42; } }); } private  T logAndCleanup(Callable callable) { try { return callable.call(); } catch (Exception e) { System.out.println("An exception has been thrown: " + e); throw new RuntimeException(e); // or return null, or whatever you want } finally { System.out.println("doing some cleanup..."); } } public static void main(String[] args) { ExceptionHandling eh = new ExceptionHandling(); System.out.println(eh.doSomething(false)); System.out.println(eh.doSomethingElse()); System.out.println(eh.doSomething(true)); } } 

编辑:使用Java 8,包装的代码可以更漂亮:

 public String doSomething(final boolean throwException) { return logAndCleanup(() -> { if (throwException) { throw new Exception("you asked for it"); } return "hello"; }); } 

您可以使用动态代理来实现此function。 这需要一些设置,但一旦完成,非常简单。

首先,定义一个接口并将注释放在界面上。

 public interface MyInterface { @TryCatchWithLogging public void doSomething(); } 

现在,当你想为消费者提供接口的实现时,不要向他提供实际的实现,而是提供给它的代理。

 MyInterface impl = new java.lang.reflect.Proxy.newProxyInstance( Impl.class.getClassLoader(), Impl.class.getInterfaces(), YourProxy(new Impl()); 

然后实现YourProxy。

 public class YourProxy implements InvocationHandler { .... public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ( method.isAnnotationPresent(TryCatchLogging.class) ) { // Enclose with try catch } 

您可以自己实现注释和注释处理器,并在每次编译时使用仪器代码( javac -processor )。 其他方法是使用AOP,比如AspectJ或Spring AOP(如果你使用Spring)。

afaik你必须监视@TryCatchWithLoggingAndCleanUp注释的每个方法调用,这将非常繁琐。 基本上你可以通过reflection得到每个方法注释,然后进行exception处理和记录。 但我不确定你会想那样做。