我有一个方法抛出从java定时器run()调用的IOException。由于run()没有返回任何已检查的异常,我使用AspectJ进行日志记录,如何在aspectj中记录异常?
这是我的代码:
timer = new Timer();
`
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
for (OidTypes oidType : typesList) {
try {
valueIncrementOperation(oidType);//------this method throws exception
} catch (IOException e) {
System.out.println("Error occured inside Timer : "
+ e.getMessage());
timer.cancel();
timer = null;
}
}
` 我现在被迫使用try / catch。我有什么选择?
答案 0 :(得分:1)
首先,您需要将IOException打包到一个未经检查的异常中,真正的异常将是您在建议中捕获的异常的原因。
最简单的方法是使用RuntimeException。
public void doTimerJob() {
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
throw new IOException("file not found");
} catch (IOException e) {
timer.cancel();
throw new RuntimeException(e);
}
}
}, new Date(), 2000);
}
然后你可以尝试以下方法:
为TimerTask#run
创建一个切点pointcut timerTaskRun() : execution(public * java.util.TimerTask.run(..) );
以及抛出RuntimeException之后的建议
after() throwing(RuntimeExceptione) : timerTaskRun() {
System.out.println("log and rethrow " + e.getCause().getMessage());
}
这将在记录后重新抛出异常。
如果你想记录并吞下例外,你可以写一个周围的建议
Object around() : timerTaskRun() {
Object o;
try {
o = proceed();
} catch(RuntimeException e) {
System.out.println("log and swallow " + e.getCause().getMessage());
o = null;
}
return o;
}
请注意,您应该只有一个建议,after throwing
或around
,而不是两者。
但您可能不希望建议所有TimerTask#run
次呼叫以及所有RuntimeException
次呼叫。在这种情况下,您应该创建自己的类型,您应该在切入点和建议中使用它们。
“未选中”IOException
public class IOExceptionUnchecked extends RuntimeException {
private static final long serialVersionUID = 1L;
public IOExceptionUnchecked(IOException e) {
super(e);
}
}
自定义TimerTask
public class MyTimerTask extends TimerTask {
Timer owner = null;
public MyTimerTask(Timer timer) {this.owner = timer;}
@Override
public void run() {
try {
throw new IOException("file not found");
} catch (IOException e) {
owner.cancel();
throw new IOExceptionUnchecked(e);
}
}
}
点切
pointcut timerTaskRun() : execution(public * com.example.MyTimerTask.run(..) );
抛出建议之后:
after() throwing(IOExceptionUnchecked e) : timerTaskRun() {
System.out.println("log and rethrow " + e.getCause().getMessage());
}
或建议
Object around() : timerTaskRun() {
Object o;
try {
o = proceed();
} catch(IOExceptionUnchecked e) {
System.out.println("log and swallow " + e.getCause().getMessage());
o = null;
}
return o;
}
答案 1 :(得分:0)
你无法摆脱try / catch块,因为IOException
是一个经过检查的异常,并且声明TimerTask#run
不会抛出任何已检查的异常。您还可以在catch块中使用其他逻辑来取消计时器。
你最近的事情就是将IOException
包裹到RuntimeException
并重新投掷。
catch(IOException){
timer.cancel();
throw new RuntimeException(e);
}
即使这样做,AspectJ也不会记录异常和堆栈跟踪。
为此,您需要使用容器(如Spring)来创建TimerTask
实例并使用AspectJ拦截器包装它。