我有像
这样的功能class Chainable {
public Chainable doStuff(String test) {
return doSomething(test, true);
}
public Chainable doStuff(String test, String test2) {
String toUse = test + test2;
return doSomething(toUse, false);
}
private Chainable doSomething(String test, boolean version) {
// do something
if (somethingBadHappened) {
throw SpecialException.generate();
}
return this;
}
}
SpecialException
是用户应该看到的异常。异常消息故意包含抛出此异常的方法。用户将致电doSomething("x")
,如果失败,则会显示"Method 'doSomething' failed with the parameters: 'test = x | version = true'"
。
但是用户并不关心方法doSomething(String, boolean)
及其参数。他使用doStuff(String)
并希望看到该功能的消息。
所以我所做的是:
public Chainable doStuff(String test) {
try {
return doSomething(test, true);
} catch (SpecialException e) {
throw SpecialException.generate(e);
}
}
将e设置为新异常的原因并正确显示"Method 'doStuff' failed with the parameters: 'test = x'"
(用户没有看到堆栈跟踪,但如果我需要调试,我可以看到究竟发生了什么)。
现在,它有效,但每次我编写一个将其工作委托给辅助函数的新函数时,我都要重复自己。问题是,我不知道应该如何使用辅助函数,因为SpecialException
根据生成的位置找到方法名称...
还有另一种更好的方法吗?
答案 0 :(得分:0)
以下是您应该做的事情:向用户显示堆栈跟踪。然后你可以使用
throw new SpecialException();
不关心会出现什么方法。
答案 1 :(得分:0)
据我所知,据我所知,使用aspect-oriented programming或AOP处理这种情况可能会很好。在Java中,您可以使用AspectJ。
首先定义"pointcut" - 代码执行中的特定时刻,例如方法调用。接下来,您将编写一个"advice",这是切入点切割时需要完成的事情。您将这两者放在一个"aspect"中,并在构建期间将它们weaven放入字节码中。
在这种情况下,您需要一个切入点来拦截Chainable
上对公共方法的调用,但不应在Chainable
内进行调用:
pointcut publicChainableMethod() : target(Chainable)
&& call(public * *(..))
pointcut firstPublicChainableMethod() : target(Chainable)
&& call(* *(..))
&& !cflowbelow(publicChainableMethod());
第一个切入点定义了对Chainable
上的公共方法的任何调用,第二个切入点定义了对Chainable
内的方法的调用,除了在第一个切入点的控制流程中不应该调用它。
接下来,您需要一个为您生成新SpecialException
的建议:
after() throwing (SpecialException e): firstPublicChainableMethod() {
throw SpecialException.generate(e);
}
免责声明:我不是AOP或AspectJ专家,所以这种方法可能无法开箱即用。