3

我在我的代码中使用 Spring AOP 来拦截某个方法的执行。我正在尝试做的一个简化示例如下:

public void someMethod() {
    //does something
}

@Around("execution( someMethod())")
public void anotherMethod(final ProceedingJoinPoint joinPoint) {
    //i want to add this to a queue to get executed later on
    addToWaitList(new Callable() {
        @Override
        public call() throws Exception {
            joinPoint.proceed();
        }
    });
    return;
}

本质上,我想推迟执行,someMethod()直到它位于列表的首位。但是,主线程阻塞,即使我在 结束时返回anotherMethod(),所以我无法将 a 添加new Callable到列表中,直到第一个完成执行。

文档说您可以通过返回自己的返回值或抛出异常来缩短建议的方法执行。我不想抛出异常,也不确定在这种情况下“返回自己的返回值”是什么意思。我希望能够使用主线程将 Callables 添加到列表中,然后让其他线程池执行它们。

4

1 回答 1

3

您希望实现的是工作对象模式。我为您创建了一个小示例,展示如何通过某种命名模式拦截方法调用,但使用可变的返回类型和参数。有关更复杂的示例,请参见我自己的答案。

驱动应用:

public class Application {
    public static void main(String[] args) {
        System.out.println("Starting up application");
        Application app = new Application();
        app.doThis(11);
        app.doThat();
        app.doThis(22);
        System.out.println("Shutting down application");
    }

    public void doThis(int number) {
        System.out.println("Doing this with number " + number);
    }

    public String doThat() {
        String value = "lorem ipsum";
        System.out.println("Doing that with text value '" + value + "'");
        return value;
    }
}

实现工作对象模式的方面:

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Callable;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class QueuedExecutionAspect {

    Queue<Callable<Object>> waitList = new LinkedList<Callable<Object>>();

    private void addToWaitList(Callable<Object> callable) {
        waitList.add(callable);
    }

    @Around("execution(public * Application.do*(..))")
    public Object anotherMethod(final ProceedingJoinPoint joinPoint) {
        System.out.println(joinPoint + " -> adding to execution queue");
        addToWaitList(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                try {
                    joinPoint.proceed();
                } catch (Throwable e) {
                    throw new Exception(e);
                }
                return null;
            }
        });
        return null;
    }

    @After("execution(public * Application.main(..))")
    public void doDelayedExecution(JoinPoint joinPoint) throws Exception {
        System.out.println("\nDelayed executions:");
        while (!waitList.isEmpty()) {
            waitList.poll().call();
        }
    }
}

输出:

Starting up application
execution(void Application.doThis(int)) -> adding to execution queue
execution(String Application.doThat()) -> adding to execution queue
execution(void Application.doThis(int)) -> adding to execution queue
Shutting down application

Delayed executions:
Doing this with number 11
Doing that with text value 'lorem ipsum'
Doing this with number 22

从输出中可以看出,在将工作对象添加到队列@Around后,通知正常终止,应用程序继续执行而没有被调用。为了说明,我添加了另一个建议,它在应用程序退出之前运行 FIFO 队列中的所有元素(可以根据您的需要使用其他队列类型)。Callableproceed()

于 2013-07-12T14:05:43.990 回答