• 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;
    }
    
  • 相关阅读:
    ASP.NET Web API 框架研究 Self Host模式下的消息处理管道
    ASP.NET Web API 框架研究 Web Host模式下的消息处理管道
    ASP.NET Web API 框架研究 核心的消息处理管道
    ASP.NET Web API 框架研究 Web Host模式路由及将请求转出到消息处理管道
    ASP.NET Web API 框架研究 ASP.NET Web API 路由
    ASP.NET Web API 框架研究 ASP.NET 路由
    ASP.NET Web API 入门 (API接口、寄宿方式、HttpClient调用)
    MVVM模式
    RESTful Web API 理解
    C# 函数式编程及Monads.net库
  • 原文地址:https://www.cnblogs.com/ybyn/p/16300670.html
Copyright © 2020-2023  润新知