无法自动装配 JobLauncher,总是 returns null
can not autowire JobLauncher, always returns null
我尝试 link 每个作业都有一个线程,这样我可以同时启动多个具有不同 cron 值的作业,但 jobLauncher 总是为空。
我试图在配置中将 jobLauncher 创建为一个 bean class 但它从来没有奏效。
@Component
public class MyTask extends Thread {
@Autowired
private ApplicationContext context;
@Autowired
private JobLauncher jobLauncher;
@Autowired
private Batchconfig config;
public void run() {
Jobs job = Scheduler.listLinked.get(this);
if (job != null && job.isState()) {
JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
.addString("param", job.getParam()).toJobParameters();
try {
JobExecution jobExecution = jobLauncher.run(config.execute(job.getName()), jobParameters);
System.out.println("Job's Status:::" + jobExecution.getStatus());
} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@Component
public class Scheduler implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
set();
for (Jobs j : list) {
MyTask th = new MyTask();
listLinkedInverse.put(j, th);
listLinked.put(th, j);
taskRegistrar.addCronTask(th, j.getCron());
}
}
}
异常:
java.lang.NullPointerException
at com.generator.config.batch.scheduler.MyTask.run(MyTask.java:39)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
MyTask
实例是手动创建的(在 MyTask th = new MyTask()
中)而不是 Spring,因此不会执行依赖注入并且自动装配的 JobLauncher
将为空.
您需要创建一个 MyTask
类型的 bean(以便正确注入其依赖项),然后将其作为协作者注入到您的 Scheduler
class 中。
附带说明一下,这不是同时启动多个作业的理想方式。您正在为每个线程创建一个 JobLauncher
,默认情况下又使用 SyncTaskExecutor
。您可以做的是创建一个 JobLauncher
并使用线程池配置它以同时启动作业,例如:
@Bean
public JobLauncher jobLauncher() {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository());
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor()); // or use ThreadPoolTaskExecutor
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
您可以在参考文档的 Configuring a JobLauncher 部分找到更多详细信息。
我尝试了这个解决方案并且有效
@Component
public class Scheduler {
@Autowired
private ApplicationContext context;
@Autowired
public static JobLauncher jobLauncher;
@Autowired
public static Batchconfig config;
@Autowired
private JobService jobService;
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public static Map<ScheduledFuture<Jobs>, Jobs> listLinked = new HashMap<>();
public static Map<Jobs, ScheduledFuture<Jobs>> listLinkedInverse = new HashMap<>();
List<Jobs> list;
@PostConstruct
public void init() {
list = jobService.findAll();
for (Jobs j : list) {
if(j.isState()) {
MyTask th = new MyTask(j);
context.getAutowireCapableBeanFactory().autowireBean(th);
ScheduledFuture<Jobs> jobHandler = (ScheduledFuture<Jobs>) scheduler.scheduleAtFixedRate(th, 0, 2, TimeUnit.SECONDS);
listLinkedInverse.put(j, jobHandler);
listLinked.put(jobHandler, j);
}
}
}
public void launchJob(Jobs myJob){
MyTask th = new MyTask(myJob);
context.getAutowireCapableBeanFactory().autowireBean(th);
ScheduledFuture<Jobs> jobHandler = (ScheduledFuture<Jobs>) scheduler.scheduleAtFixedRate(th, 0, 2, TimeUnit.SECONDS);
listLinkedInverse.put(myJob, jobHandler);
listLinked.put(jobHandler, myJob);
}
public void cancelJob(Jobs j) {
listLinkedInverse.get(j).cancel(true);
listLinked.remove(listLinkedInverse.get(j));
listLinkedInverse.remove(j);
}
}
@Component
public class MyTask extends Thread {
@Autowired
private JobLauncher jobLauncher;
private Jobs job;
@Autowired
private Batchconfig config;
public MyTask() {
}
public MyTask(Jobs job) {
this.job = job;
}
public void run() {
JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
.addString("param", job.getParam()).toJobParameters();
try {
JobExecution jobExecution = jobLauncher.run(config.execute(job.getName()), jobParameters);
System.out.println("Job's Status:::" + jobExecution.getStatus());
} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
我尝试 link 每个作业都有一个线程,这样我可以同时启动多个具有不同 cron 值的作业,但 jobLauncher 总是为空。
我试图在配置中将 jobLauncher 创建为一个 bean class 但它从来没有奏效。
@Component
public class MyTask extends Thread {
@Autowired
private ApplicationContext context;
@Autowired
private JobLauncher jobLauncher;
@Autowired
private Batchconfig config;
public void run() {
Jobs job = Scheduler.listLinked.get(this);
if (job != null && job.isState()) {
JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
.addString("param", job.getParam()).toJobParameters();
try {
JobExecution jobExecution = jobLauncher.run(config.execute(job.getName()), jobParameters);
System.out.println("Job's Status:::" + jobExecution.getStatus());
} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@Component
public class Scheduler implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
set();
for (Jobs j : list) {
MyTask th = new MyTask();
listLinkedInverse.put(j, th);
listLinked.put(th, j);
taskRegistrar.addCronTask(th, j.getCron());
}
}
}
异常:
java.lang.NullPointerException
at com.generator.config.batch.scheduler.MyTask.run(MyTask.java:39)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
MyTask
实例是手动创建的(在 MyTask th = new MyTask()
中)而不是 Spring,因此不会执行依赖注入并且自动装配的 JobLauncher
将为空.
您需要创建一个 MyTask
类型的 bean(以便正确注入其依赖项),然后将其作为协作者注入到您的 Scheduler
class 中。
附带说明一下,这不是同时启动多个作业的理想方式。您正在为每个线程创建一个 JobLauncher
,默认情况下又使用 SyncTaskExecutor
。您可以做的是创建一个 JobLauncher
并使用线程池配置它以同时启动作业,例如:
@Bean
public JobLauncher jobLauncher() {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository());
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor()); // or use ThreadPoolTaskExecutor
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
您可以在参考文档的 Configuring a JobLauncher 部分找到更多详细信息。
我尝试了这个解决方案并且有效
@Component
public class Scheduler {
@Autowired
private ApplicationContext context;
@Autowired
public static JobLauncher jobLauncher;
@Autowired
public static Batchconfig config;
@Autowired
private JobService jobService;
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public static Map<ScheduledFuture<Jobs>, Jobs> listLinked = new HashMap<>();
public static Map<Jobs, ScheduledFuture<Jobs>> listLinkedInverse = new HashMap<>();
List<Jobs> list;
@PostConstruct
public void init() {
list = jobService.findAll();
for (Jobs j : list) {
if(j.isState()) {
MyTask th = new MyTask(j);
context.getAutowireCapableBeanFactory().autowireBean(th);
ScheduledFuture<Jobs> jobHandler = (ScheduledFuture<Jobs>) scheduler.scheduleAtFixedRate(th, 0, 2, TimeUnit.SECONDS);
listLinkedInverse.put(j, jobHandler);
listLinked.put(jobHandler, j);
}
}
}
public void launchJob(Jobs myJob){
MyTask th = new MyTask(myJob);
context.getAutowireCapableBeanFactory().autowireBean(th);
ScheduledFuture<Jobs> jobHandler = (ScheduledFuture<Jobs>) scheduler.scheduleAtFixedRate(th, 0, 2, TimeUnit.SECONDS);
listLinkedInverse.put(myJob, jobHandler);
listLinked.put(jobHandler, myJob);
}
public void cancelJob(Jobs j) {
listLinkedInverse.get(j).cancel(true);
listLinked.remove(listLinkedInverse.get(j));
listLinkedInverse.remove(j);
}
}
@Component
public class MyTask extends Thread {
@Autowired
private JobLauncher jobLauncher;
private Jobs job;
@Autowired
private Batchconfig config;
public MyTask() {
}
public MyTask(Jobs job) {
this.job = job;
}
public void run() {
JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
.addString("param", job.getParam()).toJobParameters();
try {
JobExecution jobExecution = jobLauncher.run(config.execute(job.getName()), jobParameters);
System.out.println("Job's Status:::" + jobExecution.getStatus());
} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}