如何在另一个 AspectJ 方面拦截proceed()? [英] How to intercept proceed() in another AspectJ aspect?

查看:26
本文介绍了如何在另一个 AspectJ 方面拦截proceed()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的情况如下:我有一个 LoggingAspect,其中有几个切入点与我的主应用程序中的特定方法执行相匹配.对应的advice body基本上都长得差不多,造成了大量的代码重复:

I have a situation as follows: I have a LoggingAspect with several pointcuts matching specific method executions in my main application. The corresponding advice bodies basically all look similar, causing a lot of code duplication:

void around() : download() {
    String message = "Downloading, verifying (MD5) and unpacking";
    SimpleLogger.verbose(message, IndentMode.INDENT_AFTER);
    proceed();
    SimpleLogger.verbose(message + " - done", IndentMode.DEDENT_BEFORE);
}

不过有一些变化.有时切入点 &建议有一个 argthis 参数,该参数也打印到日志中.有时完成"消息不会打印,如果它只是一个小调用,没有包含很多其他调用,就像这样:

There is some variation, though. Sometimes the pointcut & advice have an arg or this parameter which is also printed to the log. Sometimes the "done" message is not printed if it s just a minor call not wrapping a lot of other calls, like this:

void around(BasicFilter filter) : fixFaultyLinkTargets()  && this(filter) {
    String message = "TOC file: checking for faulty link targets";
    SimpleLogger.verbose(message, IndentMode.INDENT_AFTER);
    proceed(filter);
    SimpleLogger.dedent();
}

不变的是我手动告诉记录器

The constant thing is that I manually tell the logger

  • 在打印第一条消息后增加缩进级别,即在调用 proceed() 之前,以及
  • 在打印最终消息之前降低缩进级别(如果有的话),即在 proceed() 返回之后.
  • to increase the indent level after the first message is printed, i.e. directly before proceed() is called, and
  • to decrease the indent level before the final message is printed (if any is printed), i.e. directly after proceed() has returned.

我的想法是,我想编写一个元方面(或称其为辅助方面),并带有一个切入点,该切入点拦截 LoggingAspect 中的 proceed() 调用,因此以便相应地自动调整缩进级别.但似乎没有切入点匹配 proceed().我已经尝试过 call(SomeMethodInMyMainApp),甚至一个切入点匹配日志方面的所有内容,但切入点匹配我不需要的任何内容,但从未进行过.

My idea is that I would like to write a meta aspect (or call it a helper aspect) with a pointcut which intercepts the proceed() calls in LoggingAspect so as to automatically adjust the indentation level accordingly. But there seems to be no pointcut matching proceed(). I have tried call(SomeMethodInMyMainApp), even a pointcut matching everything in the logging aspect, but the pointcut matches anything I do not need, but never ever the proceed.

如果有人知道我如何做到这一点,我希望得到提示或代码片段.

If anybody knows how I can do this, I would appreciate a hint or a code snippet.

这样做的一种间接方式可能不是拦截通知本身,而是拦截这些通知所建议的方法调用(或执行),方法是创建一个像这样的额外切入点:

An indirect way of doing this might be to intercept not the advice themselves, but the method calls (or executions) advised by those advice by creating an extra pointcut like this:

// ATTENTION: each new pointcut must also be added here
pointcut catchAll() : download() || fixFaultyLinkTargets() || ...;

void around() : catchAll() {
    SimpleLogger.indent();
    proceed();
    SimpleLogger.dedent();
}

不过,我更喜欢另一种方式,而不必每次更改日志记录方面的某些内容时都要记住更新额外的 catchAll() 切入点.

I would prefer another way though, without me having to remember to update the extra catchAll() pointcut everytime I change something in the logging aspect.

推荐答案

建议将proceed() 包装在匿名类中.并编写一个方面来处理这次执行(但不要忘记继续()的潜在异常).

Suggestion wrap the proceed() in an anonymous class. And the write an aspect which adress this execution (but don't forget potential exceptions of proceed()).

我的建议:

// AspectProceedCaller.java
public abstract class AspectProceedCaller { 
    public abstract Object doProceed(); 
};

// aspect ProceedCallerAspect.aj
aspect ProceedCallerAspect {
     pointcut execProceedCaller() : execution( * AspectProceedCaller+.doProceed() );

     Object around() : execProceedCaller() {
         try {
              SimpleLogger.indent();
              return proceed();
         }
         finally {
              SimpleLogger.dedent();
         }
     }
};


// Your application aspect 
aspect AnyAspect {
    pointcut anyPointcut() : ...;

    Object around() : anyPointcut() {
        AspectProceedCaller apc=new AspectProceedCaller() {
            public Object doProceed() {
                return proceed();
            }
        };  

        // DO Stuff before ....

        Object retval = apc.doProceed();

        // ... and after calling proceed.

        return retval;
    }
};

最好的问候马可

这篇关于如何在另一个 AspectJ 方面拦截proceed()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆