AOP使用Around来避免执行方法

时间:2013-06-14 18:16:16

标签: java spring aop spring-aop

我在我的代码中使用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()结束时返回,因此我无法在列表中添加new Callable,直到第一个执行完毕。

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

1 个答案:

答案 0 :(得分:3)

您希望实施的是工作者对象模式。我已经创建了一个小例子,展示了如何通过某种命名模式拦截方法调用,但是具有可变的返回类型和参数。有关更复杂的示例,请参阅my own answer there

驱动程序应用程序:

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