如何自动连接弹簧任务执行器创建的线程?

2022-09-04 19:58:32

根据Spring的文档,使用TaskExecutor的方式如下:

import org.springframework.core.task.TaskExecutor;

public class TaskExecutorExample {

  private class MessagePrinterTask implements Runnable {

    private String message;

    public MessagePrinterTask(String message) {
      this.message = message;
    }

    public void run() {
      System.out.println(message);
    }

  }

  private TaskExecutor taskExecutor;

  public TaskExecutorExample(TaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
  }

  public void printMessages() {
    for(int i = 0; i < 25; i++) {
      taskExecutor.execute(new MessagePrinterTask("Message" + i));
    }
  }
}

但是,如果 MessagePrinterTask 具有自动连接的依赖项,则 Spring 不会配置它们,因为我们在 Spring 的上下文之外实例化了我们的 Bean(至少我是这样理解的),即使 Spring 将提供实际的线程创建。如果MessagePrinterTask具有自动连接的依赖项,我们如何让Spring识别它们?我尝试了以下修改后的示例,但无济于事(是的,自动布线已正确启用):

import org.springframework.core.task.TaskExecutor;

public class TaskExecutorExample {

  @Component
  private class MessagePrinterTask implements Runnable {

    @Autowired
    private autoWiredDependency;

    public void run() {
      autoWiredDependency.doNotThrowNullPointerExceptionPlease();
    }

  }

  private TaskExecutor taskExecutor;

  public TaskExecutorExample(TaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
  }

  public void printMessages() {
    for(int i = 0; i < 25; i++) {
      taskExecutor.execute(new MessagePrinterTask());
    }
  }
}

答案 1

我认为您可以通过两种方式做到这一点:

一个。为任务提供依赖项 - 这样:

class MessagePrinterTask implements Runnable {
    public MessagePrinterTask(ADependency aDependency){
        this.aDependency = aDependency;
    }


    private ADependency aDependency;

    public void run() {
        aDependency.doNotThrowNullPointerExceptionPlease();
    }
}

在您的 TaskExectorExample 中,它可以是单例:

import org.springframework.core.task.TaskExecutor;

public class TaskExecutorExample {

  @Autowired  private ADependency aDependency;

  @Autowired
  public TaskExecutorExample(TaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
  }

  public void printMessages() {
    for(int i = 0; i < 25; i++) {
      taskExecutor.execute(new MessagePrinterTask(this.aDependency));
    }
  }
}

b. 在 MesasgePrinterTask 上使用@Configurable注释,这会将依赖项注入 MessagePrinterTask 中,即使它是在 Spring 容器外部实例化的 - 但是使用 @Configurable时会有一些问题(需要 AspectJ):

@Configurable
class MessagePrinterTask implements Runnable {

答案 2

您还可以使用@Async批注。

public class TaskExecutorExample {

    @Autowired
    private MessagePrinterTask task;

    public void printMessages() {
        for(int i = 0; i < 25; i++) {
            task.printMessage();
        }
    }
}

@Component
public class MessagePrinterTask implements Runnable {

    @Autowired
    private String message;

    @Async
    public void printMessage() {
      System.out.println(message);
    }

}

对 printMessage() 的任何调用都将使用默认执行器异步执行,您可以使用 Spring xml 配置中的以下内容对其进行配置。

<task:annotation-driven executor="myExecutor"/>
<task:executor id="myExecutor" pool-size="5" />