У меня есть класс, из которого я хочу запускать задания асинхронно. Для этого у меня есть следующий код:
@Resource
private SimpleJobLauncher jobLauncher;
@PostConstruct
public void initLauncher(){
jobLauncher.setTaskExecutor(taskExecutor());
}
Однако есть ситуация, когда мне нужно делать это синхронно. Итак, я добавил следующую переменную:
@Resource
private SimpleJobLauncher synchronousJobLauncher;
Я надеялся, что на нем не будет taskExecutor, что сделает его синхронным. Затем я передаю synchronousJobLauncher туда, где я хочу делать что-то синхронно. Однако использование synchronousJobLauncher дает мне ту же ошибку, что и при использовании асинхронного, что наводит меня на мысль, что вы не можете автоматически подключать одну и ту же переменную дважды, как я пытаюсь это сделать. Если я не выполняю часть кода @PostConstruct, синхронная часть работает так, как я ожидал, но не асинхронная часть, даже если они используют, как я думаю, разные средства запуска заданий.
Любые идеи? Я пробовал использовать аннотацию @Resource вместо @Autowired.




Я не использовал SimpleJobLaunchers, но обычно в Spring я всегда использовал аннотацию @Async, которая упрощает асинхронное выполнение. Все, что вам нужно сделать, это добавить эту аннотацию @EnableAsync в любой файл конфигурации, как показано ниже.
@Configuration
@EnableAsync
public class MvcConfig extends WebMvcConfigurerAdapter { ... }
Теперь все о добавлении @Async к любому методу, который будет работать асинхронно.
@Component
class AsyncTask {
@Async
public Future<String> run() throws InterruptedException {
return new AsyncResult<String>("return value");
}
}
А если вы хотите дождаться результата, вы можете сделать следующее.
public void callAsyncTask() {
try {
Future<String> future = asyncTask.run();
// Do some other things while the async task is running.
// future.get() will block the function and wait for the result.
String asyncResult = future.get();
} catch(InterruptedException e) {
e.printStackTrace();
// Do something else.
}
}
Надеюсь это поможет. Я знаю, что это не совсем то, о чем вы просили, но, возможно, это решение может облегчить вашу проблему.
Вы можете создать две программы запуска заданий (одну синхронную и одну асинхронную), а затем ввести нужную, используя квалификатор. По умолчанию SimpleJobLauncher использует синхронный исполнитель задач, поэтому вам нужно настроить исполнитель задач только для асинхронного. Вот пример:
@Bean
public SimpleJobLauncher synchronousJobLauncher() {
return new SimpleJobLauncher();
}
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
return new ThreadPoolTaskExecutor();
}
@Bean
public SimpleJobLauncher asynchronousJobLauncher() {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setTaskExecutor(threadPoolTaskExecutor());
return jobLauncher;
}
Затем введите желаемое средство запуска заданий с @Qualifier("synchronousJobLauncher") или @Qualifier("asynchronousJobLauncher") в соответствии с вашими потребностями.
Надеюсь это поможет.