Art*_*tem 8 java copy-paste exception
当我不得不为数据库和网络操作进行重试时,我有多种情况.无论我到哪里,我都有以下类型的代码:
for (int iteration = 1; ; iteration++) {
try {
data = doSomethingUseful(data);
break;
} catch (SomeException | AndAnotherException e) {
if (iteration == helper.getNumberOfRetries()) {
throw e;
} else {
errorReporter.reportError("Got following error for data = {}. Continue trying after delay...", data, e);
utilities.defaultDelayForIteration(iteration);
handleSpecificCase(data);
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是这个代码模式在我的类中被复制粘贴.这真的很糟糕.我无法弄清楚如何摆脱这种for-break-catch复制粘贴模式,因为我通常会得到不同的异常来处理,我想记录我失败的数据(通常也是不同的方式).
有没有一种方法可以避免Java 7中的这种复制粘贴?
编辑:我确实使用guice进行依赖注入.我确实检查了异常.可能有多个变量而不是一个数据,它们都是不同的类型.
编辑2:AOP方法对我来说是最有希望的.
副手,我可以想到两种不同的方法:
如果可以以声明方式表示异常处理中的差异,则可以使用AOP编写围绕方法的异常处理代码.然后,您的业务代码可能如下所示:
@Retry(times = 3, loglevel = LogLevel.INFO)
List<User> getActiveUsers() throws DatabaseException {
// talk to the database
}
Run Code Online (Sandbox Code Playgroud)
优点是很容易向方法添加重试行为,缺点是编织建议的复杂性(你只需要实现一次.如果你使用依赖注入库,很可能会提供方法拦截)支持).
另一种方法是使用命令模式:
abstract class Retrieable<I,O> {
private final LogLevel logLevel;
protected Retrieable(LogLevel loglevel) {
this.logLevel = loglevel;
}
protected abstract O call(I input);
// subclasses may override to perform custom logic.
protected void handle(RuntimeException e) {
// log the exception.
}
public O execute(I input) {
for (int iteration = 1; ; iteration++) {
try {
return call(input);
} catch (RuntimeException e) {
if (iteration == helper.getNumberOfRetries()) {
throw e;
} else {
handle();
utilities.defaultDelayForIteration(iteration);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
命令模式的问题是方法参数.您被限制为单个参数,并且对于调用者而言,泛型相当不实用.此外,它不适用于已检查的异常.从好的方面来说,没有花哨的AOP东西:-)
如前所述,AOP 和 Java 注释是一个不错的选择。我会建议使用jcabi-aspects 中的一种只读机制:
@RetryOnFailure(attempts = 2, delay = 10, verbose = false)
public String load(URL url) {
return url.openConnection().getContent();
}
Run Code Online (Sandbox Code Playgroud)
另请阅读此博客文章:http : //www.yegor256.com/2014/08/15/retry-java-method-on-exception.html