有什么方法可以使用 AOP 拦截 Runnable

Is there any ways to intercept a Runnable using AOP

这是我的问题。

我有一个 class 实现 Runnable,它是一个守护线程,它将在应用程序生命周期中永久存在。

现在想做一个类似AOP增强的功能来增强这个Runnableclass。

如果 class 被@Service 或@Component 注释,那么很容易获得该切入点。但现在它是一个 class 实现了 Runnable 接口,所以我还没有找到任何可能的方法来做到这一点而不会对原始代码造成任何干扰。

下面是我的测试代码:

这是我的守护线程的父接口

public interface MessageRunnable extends Runnable {
    void doConsume();
}



工作线程之一:

@Slf4j
public class MyDaemonThread implements MessageRunnable{
    @Override
    public void run() {
        log.info("now in run function,ready to call doConsume...");
        while(true){
            log.info("I m still alive...");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            doConsume();
        }
    }

    @Override
    public void doConsume() {
        log.info("doConsume was called...");
    }
}



这是简单的测试:

@Component
public class TestComponent {
    private MyDaemonThread testThread;
    @PostConstruct
    public void init(){
        if(testThread==null){
            testThread=new MyDaemonThread();
            new Thread(testThread).start();
        }
    }
}



运行申请后。

我可以看到日志打印得很好,但是现在如果我想在调用 doConsume 函数之前添加一个函数来打印 now I'm in the aspect method,我不知道在不影响我的源代码的情况下这样做,添加代码是可以接受的,但根本不允许修改。

不知有没有什么办法可以让spring来处理这个守护线程,那么切入切面就很容易了。否则,我必须更改代码以添加代理方法和拦截器来实现目标....

首先,MyDaemonThread 实例不是 spring 容器管理的 bean。该代码使用 new 关键字来创建实例。 Spring AOP 只能通知一个 spring bean。

即使 MyDaemonThread 是一个 spring bean,也不可能建议 doConsume() 使用 Spring AOP 和当前代码(OP 提到没有修改是允许的)。

来自reference documentation

Due to the proxy-based nature of Spring’s AOP framework, calls within the target object are, by definition, not intercepted.