Состояние компонента Springboot сохраняется при выполнении нового запроса.. Проблема с параллелизмом?

#spring-boot #concurrency #components #state #autowired

#spring-boot #параллелизм #Компоненты #состояние #автоматическое подключение

Вопрос:

У меня есть приложение SpringBoot, которое предоставляет простой REST-api через @RestController. Выполняется загрузка файла и попытка считывания значений из загруженного файла Excel.

Проблема в том, что «состояние» какого-либо компонента, похоже, не сбрасывается при новом запросе, как будто это какая-то проблема с параллелизмом.. Кажется, я не могу понять это. Например, когда я делаю новый последующий запрос после первого, значения из предыдущего запроса все еще висят в ImportProcessor и последующих объектах, он не сбрасывается, и я не могу понять, почему..

Уровень обслуживания приложения @автоматически подключает компонент «ImportProcessor», который содержит множество полей, которые изменяются с помощью его методов. Пример:

 @Component
@NoArgsConstructor
@Slf4j
public class ImportProcessor {

    public static STATE processState = STATE.READY;
    
    @Autowired
    RegulativImporter regulativImporter;

    @Autowired
    DatabaseImporter databaseImporter;

    Sheet strekning;
    Sheet strekning_periode;

    HashMap<Long, TakstkategoriEntity> successfulTakstkategori;
    HashMap<Long, RegulativEntity> successfulRegulativ;
    HashMap<Long, TakstEntity> successfulTakst;

        public ImportJobInfo handleStartProcessingRequest(Workbook workbook) throws FailedToStartProcessingException {
        if (processState == STATE.READY) {
            setProcessState(STATE.IMPORTING);
            ImportJobInfo importJobInfo = startProcessing(workbook);
            cleanUpState();
            return importJobInfo;
        } else {
            throw new FailedToStartProcessingException("Failed to start processing because of insufficient state:",
                processState);
        }
    }

   // Methods that modify and set these objects.. Changes state based on action, initialize hashMaps..
   // Method that inserts part of the Hashmaps to a database using DatabaseImporter
}
 

Вот вызывающая служба:

 @Service
@Slf4j
public class FergeregisterImportServiceImpl implements FergeregisterImportService {

    @Autowired
    ImportProcessor importProcessor;

    @Override
    public ImportJobInfo startImportJob(MultipartFile file) throws FailedToStartProcessingException {
        
        InputStream excelInputStream;
        Workbook workbook;
        ImportJobInfo importJobInfo = null;

        try {
            excelInputStream = file.getInputStream();
            workbook = new XSSFWorkbook(excelInputStream);
            log.info("Successfully converted Excel inputstream to Apache-POI workbook.");
        } catch (IOException e) {
            log.error(e.getMessage()   " | cause: "   e.getCause());
            throw new FailedToStartProcessingException("Failed to convert Excel inputstream to Apache-POI workbook.",
                STATE.FAILED);
        }

        try {
            importJobInfo = importProcessor.handleStartProcessingRequest(workbook);
        } catch (FailedToStartProcessingException e) {
            log.error(e.getMessage(), importProcessor.getProcessState());
            throw e;
        }

        return importJobInfo;
    }
   // Some other methods..
}
 

Если я не @Autowire ImportProcessor, он работает нормально, и у меня нет проблем с параллелизмом. Но тогда кажется абсолютно невозможным, чтобы ImportService вызывал @Autowired DatabaseImporter, который является интерфейсом CrudRepository

Если бы я только мог убедиться, что у ImportProcessor был новый старт для каждого нового запроса, все работало бы так, как задумано. Я действительно надеюсь, что смогу получить здесь несколько советов. Спасибо!

Ответ №1:

Spring Boot основан на одноэлементной модели, если вы не указали область действия компонента, что означает, что каждый компонент, который вы указываете как компонент (@Component, @Service или что-то еще), когда вы @Autowired этот компонент независимо от того, где он находится, всегда будет одним и тем же экземпляром, и именно поэтому ваше состояние несброс.

Надеюсь, это поможет ответить на ваш вопрос.