java - AspectJ:如何记录方法的成功完成?

标签 java aspectj

因此,我正在与 AspectJ 一起重构我的程序,以删除主类中的所有日志记录调用。相反,所有日志记录调用都将通过方面进行。到目前为止,我已成功完成以下操作:

  • 捕获所有异常。由于我一开始就已经有了相当统一的异常处理(异常会向上传播调用堆栈,直到到达我的 Controller ,然后被捕获),因此这并不是太困难。使用handle(Exception),我将每个catch block 绑定(bind)到一个方面,该方面将在catch block 执行之前记录异常。

  • 调试信息记录。基本的事情,比如输入特定方法等。同样,使用 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() returned(Object o) 建议来完成此任务。如果抛出异常,该建议将不会运行,因为该方法将无法正确返回。

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

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

最佳答案

您当然可以使用切入点来包装调用堆栈中的任何内容,包括 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带有示例的文章解释了日志记录方法的进入和退出。

关于java - AspectJ:如何记录方法的成功完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32853285/

相关文章:

java - 如何从现有 Dataframe 创建 Dataframe 并将特定字段设为 Struct 类型?

java - UrlEncodedFormEntity 替换

java - 如何在具有周围建议的构造函数上应用切入点?

java - AspectJ:方法的多态日志记录。切入点签名问题

maven - 在 Maven 项目中放置方面的地方

java - 如何在Keycloak身份验证之前调用javax.servlet.Filter

java - 使用 Lambda 表达式的线程

java - 如何使 key 'H'打印一些文本

java - 编织外部 jar 中的 Aspectj

spring - 不应该建议自调用,但确实如此