ExecutorService的ThreadPool工作线程不会调用自动装配的成员变量方法

时间:2019-05-19 05:08:50

标签: java spring-boot executorservice threadpoolexecutor

我有一个名为WatermarkEventProcessorService的类,其中包含一些自动装配的成员变量。 WatermarkEventProcessorService将作为任务传递到FixedThreadPool中。

问题是,ThreadPool工作线程没有调用WatermarkEventProcessorService的自动装配变量的方法。一旦自动装配成员的方法被调用,工作线程就停止处理。

下面是创建ThreadPool的方法:

 public void processWatermarkEventObjects(List<WatermarkEventObject> waterEventObjectList) {    

        ExecutorService executor = Executors.newFixedThreadPool(1);

        for (WatermarkEventObject watermarkEventObject : waterEventObjectList) {
            executor.submit(new WatermarkEventProcessorService(watermarkEventObject));
        }

        executor.shutdown();
    }

下面是WatermarkEventProcessorService

@Service
public class WatermarkEventProcessorService implements Runnable {

    @Autowired
    private WatermarkEventObject watermarkEventObject;

    @Autowired
    private ApplicationAPIService apiService;

    public WatermarkEventProcessorService(WatermarkEventObject watermarkEventObject) {
        this.watermarkEventObject = watermarkEventObject;
    }

    private boolean prismIdExists(WatermarkEventObject watermarkEventObject) {

        return watermarkEventObject.getPrismId() != null && watermarkEventObject.getPrismId().length() > 0 ? true
                : false;
    }

    public ApplicationRecord findApplicationRecordByPrismId(String prismId) {

        System.out.println("Inside findApplicationByPrismId");
        // Prism Id Exists in Table: Application?
        // Call RESTful Web Service to retrieve Application record by Prism Id from
        // MySQL database.

        System.out.println("about to invoke apiService.getApplicationByPrismId()");
        ApplicationRecord applicationRecord = apiService.getApplicationByPrismId(prismId); //doesn't get invoked for some reason...
        System.out.println("returned from apiService.getApplicationByPrismId()");

        return applicationRecord;
    }

    @Override
    public void run() {
        System.out.println("Starting Processor thread.");

        // Validate that PrismId exists, else write to error log file, for now.
        // TODO: Please note that we will need to look up MOTS info & create new
        // Application.
        if (prismIdExists(watermarkEventObject)) {

            System.out.println("within the if block");
            // Gets the application record for the given prism id, or creates
            // a new application record in the database if we dont have one
            ApplicationRecord appRecord = findApplicationRecordByPrismId(watermarkEventObject.getPrismId());
            System.out.println("Returned from findApplicationByPrismId");
        }

        System.out.println("Completed Processor thread.");
    }
}

当我运行该应用程序时,它执行得很好,但是最后到达的打印语句是“即将调用apiService.getApplicationByPrismId()”。以下日志语句“从apiService.getApplicationByPrismId()返回”永远不会输出,也不会抛出异常。

我还在apiService.getApplicationByPrismId(prismId)方法的最开始添加了一条print语句,但是它从不执行。这表明该方法从未真正被调用:

下面是未被调用(但应该被调用)的方法:

@Cacheable("applications")
    public ApplicationRecord getApplicationByPrismId(String prismId) {

        System.out.println("inside getApplicationByPrismId"); //never gets printed
        ApplicationRecord applicationRecord = null;
        ApplicationResults resultList = new ApplicationResults();
.
.
.
}

以下是相关的控制台日志:

Starting Processor thread. within the if block Inside findApplicationByPrismId about to invoke apiService.getApplicationByPrismId() Starting Processor thread. within the if block Inside findApplicationByPrismId about to invoke apiService.getApplicationByPrismId() Starting Processor thread. within the if block Inside findApplicationByPrismId about to invoke apiService.getApplicationByPrismId()

这是怎么了?

2 个答案:

答案 0 :(得分:2)

Spring bean是基本上由Spring框架管理的bean。

@Autowired和其他注释仅影响(仅对弹簧豆有用)。

由Spring进行管理意味着Spring自己创建对象(通过调用new

但这不是代码段中发生的情况:

 for (WatermarkEventObject watermarkEventObject : waterEventObjectList) {
        executor.submit(new WatermarkEventProcessorService(watermarkEventObject));
 }

这里WatermarkEventProcessorService是由应用程序本身创建的,因此Spring不知道其为bean,因此不会对其进行任何自动装配

关于解决方案:

请注意,尽管在类WatermarkEventObject的相应字段上放置了自动装配注释,但您已经传递了WatermarkEventProcessorService的实例 因此,为什么不完全删除@Autowired并仅传递一个附加参数,使该类完全不受spring管理。

如果您需要通过Spring管理此类,请考虑使用Scope Prototype Scope,并根据要求使用某种提供程序创建此类对象。

答案 1 :(得分:2)

您应该传递spring容器创建的对象,以允许spring管理您的依赖项:

@Autowired
WatermarkEventProcessorService watermarkEventProcessorService; //injection by field for brevity

public void processWatermarkEventObjects(List<WatermarkEventObject> waterEventObjectList) {    

    ExecutorService executor = Executors.newFixedThreadPool(1);

    for (WatermarkEventObject watermarkEventObject : waterEventObjectList) {
        executor.submit(watermarkEventProcessorService);
    }

    executor.shutdown();
}