AOP Using Around to avoid executing a method

拈花ヽ惹草 提交于 2019-12-08 00:31:14

问题


I am using Spring AOP in my code to intercept the execution of a certain method. A simplified example of what I'm trying to do is below:

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;
}

Essentially, I want to hold off the execution of someMethod() until it is at the head of the list. However, the main thread blocks, even though I return at the end of anotherMethod(), so I am unable to add a new Callable to the list until the first one is done executing.

The documentation says you can shortcut the advised method execution by returning its own return value or throwing an exception. I don't want to throw an exception and am not really sure what "returning its own return value" means in this case. I want to be able to add the Callables to the list with the main thread and then have some other threadpool executing them.


回答1:


What you wish to implement is the worker object pattern. I have created a small example for you showing how you can intercept method calls with by a certain naming pattern, but with variable return types and parameters. See my own answer there for a more complex example.

Driver application:

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;
    }
}

Aspect implementing worker object pattern:

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();
        }
    }
}

Output:

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

As you can see from the output, the @Around advice terminates normally after having added the Callable worker object to the queue, application execution continues without proceed() having been called. For illustration I added another advice which runs all elements from the FIFO queue (other queue types can be used according to your needs) before the application exits.



来源:https://stackoverflow.com/questions/17114843/aop-using-around-to-avoid-executing-a-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!