在java计时器中实现aspectj日志记录

时间:2013-11-13 22:08:15

标签: java spring-mvc timer aspectj aspect

我有一个方法抛出从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。我有什么选择?

2 个答案:

答案 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 throwingaround,而不是两者。

但您可能不希望建议所有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拦截器包装它。