【问题标题】:AspectJ: How to log the successful completion of a method?AspectJ:如何记录一个方法的成功完成?
【发布时间】:2015-09-30 05:11:44
【问题描述】:

所以我正在使用 AspectJ 重构我的程序以从主类中删除所有日志记录调用。相反,所有日志调用都将通过方面发生。到目前为止,这是我成功完成的工作:

  • 捕获所有异常。由于我的异常处理一开始就非常统一(异常向上传播调用堆栈,直到它们到达我的控制器,然后被捕获),这并不太难。使用 handle(Exception) 我将每个 catch 块都绑定到一个方面,该方面将在 catch 块执行之前记录异常。

  • 调试信息记录。输入特定方法等基本操作。同样,使用 before() 以及有时使用 args() 或 thisJoinPoint.getArgs() 来捕获参数相对简单。

不过,我需要做的最后一件事是正确记录关键方法的成功完成。这是我程序中当前存在的代码块的一个小例子,所以我可以在这里更好地解释我的意思:

private static void loadDefaultProperties(){
    defaultProperties = new Properties();

    try {
        defaultProperties.load(
                Main.class.getClassLoader().getResourceAsStream(
                        "default.properties"));

        if(defaultProperties.size() == 0){
            throw new IOException();
        }

        //THE CURRENT LOGGING LINE THAT NEEDS TO BE MOVED TO AN ASPECT
        LOGGER.logp(Level.INFO, Main.class.getName(),
                "loadDefaultProperties()",
                "Default Properties file loaded successfully");

    }
    catch (IOException ex){
        //THIS EXCEPTION IS LOGGED USING HANDLE(EXCEPTION) IN AN ASPECT
        displayExceptionDialog(ex);
    }
}

因此,此方法从类路径加载默认属性。如果失败,则抛出 IOException。但是,如果没有抛出异常,并且它成功执行了任务,我也想记录它。

这个特殊的例子是一个相对较小的项目,不会错过太多,但这是应用程序中当前使用的样式。

如何将 AspectJ 中的切入点/建议配置为仅在此方法完成后运行,并识别它是否成功?

PS。我已经考虑将异常进一步传播到调用堆栈。这将允许我使用一个简单的 after() 返回(Object o) 建议来完成此操作。如果抛出异常,该通知将不会运行,因为该方法不会正确返回。

问题在于调用堆栈中没有比这更高的级别。在我的示例中,此特定方法在程序初始化后立即由我的 main 方法直接调用。在我的控制器类中,我的所有方法在调用堆栈中也只有一层。

我想我可以这样做,但我想先看看是否有其他选择,而不是将所有这些异常集中在一个地方。

【问题讨论】:

  • 您是否尝试过使用around 建议?

标签: java aspectj


【解决方案1】:

您当然可以使用切入点来包装调用堆栈中的任何内容,包括main()

public aspect WrapMain
{
    pointcut mainMethod() : execution(public static void main(String[]));
    before() : mainMethod() {
        System.out.println("Starting application...");
    }
    after() : mainMethod() {
        System.out.println("Terminating application...");
    }
}

如果您使用 Java 生成方面,则可以使用 @AfterReturning@AfterThrowing 注释来管理成功或异常情况。

@Pointcut("execution(your-method-signature-here)
public void yourPointcut(){}

@AfterReturning(pointcut = "yourPointcut()", returning ="returnValue")
public void afterSuccessAdvice(JoinPoint jp, Object returnValue) {
    // log here
}

@AfterThrowing(pointcut = "yourPointcut()", returning ="returnValue")
public void afterFailureAdvice(JoinPoint jp, Object returnValue) {
    // log here
}

这是一篇 Javaworld 文章,其中包含解释日志记录方法进入和退出的示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-19
    • 2021-06-02
    • 1970-01-01
    • 2021-12-18
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多