1

我有一个抛出 IOException 的方法,该方法是从 java 计时器 run() 调用的。由于 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。我有哪些选择?

4

2 回答 2

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呼叫以及所有RuntimeExceptions。在这种情况下,您应该创建自己的类型,您应该在切入点和建议中使用它们。

“未检查” IOException

public class IOExceptionUnchecked extends RuntimeException {
    private static final long serialVersionUID = 1L;
    public IOExceptionUnchecked(IOException e) {
        super(e);
    }
}

自定义定时器任务

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;
}
于 2013-11-14T00:15:28.067 回答
0

您无法摆脱 try/catch 块,因为IOException它是一个已检查的异常,并且TimerTask#run被声明为不抛出任何已检查的异常。此外,您在 catch 块中有额外的逻辑来取消计时器。

你能做的最接近的事情是将它包裹起来IOExceptionRuntimeException重新扔掉它。

   catch(IOException){
        timer.cancel();
        throw new RuntimeException(e);
    }

即使这样做,AspectJ 也不会记录异常和堆栈跟踪。为此,您需要使用容器(如 Spring)来创建TimerTask实例并用 AspectJ 拦截器包装它。

于 2013-11-13T22:38:43.627 回答