• Job中无法注入Bean


    环境

    • SpringBoot 2.6.4
    • Quartz 2.3.2

    现象

    在JOB对象中,使用@Autowire注解注入spring的bean对象,抛出空指针异常;

    源码分析

    scheduler使用SchedulerFactoryBean对象获取,获取方式是

    Scheduler scheduler = schedulerFactoryBean.getScheduler();
    

    因为springBoot集成了spring-boot-starter-quartz,因此可以在QuartzAutoConfiguration配置类中找到SchedulerFactoryBean的定义,如下所示:

    
    @Bean
    @ConditionalOnMissingBean
    public SchedulerFactoryBean quartzScheduler(QuartzProperties properties,
    		ObjectProvider<SchedulerFactoryBeanCustomizer> customizers, ObjectProvider<JobDetail> jobDetails,
    		Map<String, Calendar> calendars, ObjectProvider<Trigger> triggers, ApplicationContext applicationContext) {
    	SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
    	SpringBeanJobFactory jobFactory = new SpringBeanJobFactory();
    	jobFactory.setApplicationContext(applicationContext);
    	schedulerFactoryBean.setJobFactory(jobFactory);
    	//省略其他代码
    	return schedulerFactoryBean;
    }
    
    

    通过上述代码可以看到SchedulerFactoryBean设置类工厂类SpringBeanJobFactory,进入该类可以看到该类继承了AdaptableJobFactory类,并且实现了ApplicationContextAware接口,查看该类的创建job实例的方法,如下所示:

    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
    	Object job = this.applicationContext != null ? this.applicationContext.getAutowireCapableBeanFactory().createBean(bundle.getJobDetail().getJobClass(), 3, false) : super.createJobInstance(bundle);
    	if (this.isEligibleForPropertyPopulation(job)) {
    		//省略其他代码
    	}
    	return job;
    }
    

    该方法中通过applicationContext获取到AutoWireCapableBeanFactory,进而去创建bean,也即将创建的JOB对象同时注入到spring容器中,那么也就是说在该版本的springboort中,默认情况下在JOB中注入bean是可以实现的。

    不能注入原因

    按照上面的分析,默认情况下,在job中注入bean是可以正常使用的,那么为什么还是出现了NullPonterException呢?原因在于项目中因为要设置Quarz的数据源,重新定义了SchedulerFactoryBean,原始代码如下:

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
    	SchedulerFactoryBean factory = new SchedulerFactoryBean();
    	factory.setDataSource(dataSource);
    	return factory;
    }
    

    这就覆盖了QuartzAutoConfiguration配置中的原始定义,此时的JOB是没有交给spring容器管理的,也就导致了注入其他bean时会出现空指针;

    解决方案

    在重写的配置类中,添加SpringBeanJobFactory对象,如下所示:

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
    	SchedulerFactoryBean factory = new SchedulerFactoryBean();
    	factory.setDataSource(dataSource);
        //关键代码
    	SpringBeanJobFactory jobFactory = new SpringBeanJobFactory();
    	jobFactory.setApplicationContext(applicationContext);
    	factory.setJobFactory(jobFactory);
        //关键代码
    	return factory;
    }
    
  • 相关阅读:
    和至少为 K 的最短子数组
    使用VS code编写C++无法实时检测代码的解决办法
    anaconda安装VSCODE后,python报错
    神经网络中sigmod函数和tanh函数的区别
    获取本机IP
    windows C++捕获CMD命令输出
    windows下面生成 dump
    windows 控制台命令输出 捕获
    不使用PEM 文件建立SSL通道
    OpenSSL socket 服务端
  • 原文地址:https://www.cnblogs.com/ybyn/p/16300670.html
Copyright © 2020-2023  润新知