AOP 使用Around 避免执行方法 [英] AOP Using Around to avoid executing a method

查看:129
本文介绍了AOP 使用Around 避免执行方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

本质上,我想推迟 someMethod() 的执行,直到它位于列表的头部.但是,主线程阻塞,即使我在 anotherMethod() 的末尾返回,所以我无法将 new Callable 添加到列表中,直到第一个是执行完毕.

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.

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

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.

推荐答案

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

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.

驱动程序应用:

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

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.

这篇关于AOP 使用Around 避免执行方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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